Merge "Improve pty unit test to catch the bug more easily."
diff --git a/libc/Android.bp b/libc/Android.bp
index 39bd2ec..69eba45 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -1538,7 +1538,6 @@
         "bionic/sys_time.cpp",
         "bionic/sysinfo.cpp",
         "bionic/syslog.cpp",
-        "bionic/system_properties.cpp",
         "bionic/tdestroy.cpp",
         "bionic/termios.cpp",
         "bionic/thread_private.cpp",
@@ -1552,6 +1551,12 @@
         "bionic/wctype.cpp",
         "bionic/wcwidth.cpp",
         "bionic/wmempcpy.cpp",
+        "system_properties/context_node.cpp",
+        "system_properties/contexts_split.cpp",
+        "system_properties/prop_area.cpp",
+        "system_properties/prop_info.cpp",
+        "system_properties/system_properties.cpp",
+
 
         // This contains a weak stub implementation of __find_icu_symbol for wctype.cpp,
         // which will be overridden by the actual one in libc.so.
diff --git a/libc/bionic/grp_pwd.cpp b/libc/bionic/grp_pwd.cpp
index 50fcbce..43a5032 100644
--- a/libc/bionic/grp_pwd.cpp
+++ b/libc/bionic/grp_pwd.cpp
@@ -195,6 +195,89 @@
   return NULL;
 }
 
+// These are a list of the reserved app ranges, and should never contain anything below
+// AID_APP_START.  They exist per user, so a given uid/gid modulo AID_USER_OFFSET will map
+// to these ranges.
+static constexpr struct {
+  uid_t start;
+  uid_t end;
+} user_ranges[] = {
+  { AID_APP_START, AID_APP_END },
+  { AID_CACHE_GID_START, AID_CACHE_GID_END },
+  { AID_EXT_GID_START, AID_EXT_GID_END },
+  { AID_EXT_CACHE_GID_START, AID_EXT_CACHE_GID_END },
+  { AID_SHARED_GID_START, AID_SHARED_GID_END },
+  { AID_ISOLATED_START, AID_ISOLATED_END },
+};
+
+static constexpr bool verify_user_ranges_ascending() {
+  auto array_size = arraysize(user_ranges);
+  if (array_size < 2) return false;
+
+  if (user_ranges[0].start > user_ranges[0].end) return false;
+
+  for (size_t i = 1; i < array_size; ++i) {
+    if (user_ranges[i].start > user_ranges[i].end) return false;
+    if (user_ranges[i - 1].end > user_ranges[i].start) return false;
+  }
+  return true;
+}
+
+static_assert(verify_user_ranges_ascending(), "user_ranges must have ascending ranges");
+
+static bool is_valid_app_id(id_t id) {
+  id_t appid = id % AID_USER_OFFSET;
+
+  // AID_OVERFLOWUID is never a valid app id, so we explicitly return false to ensure this.
+  // This is true across all users, as there is no reason to ever map this id into any user range.
+  if (appid == AID_OVERFLOWUID) {
+    return false;
+  }
+
+  // If we've resolved to something before app_start, we have already checked against
+  // android_ids, so no need to check again.
+  if (appid < user_ranges[0].start) {
+    return true;
+  }
+
+  // Otherwise check that the appid is in one of the reserved ranges.
+  for (size_t i = 0; i < arraysize(user_ranges); ++i) {
+    if (appid >= user_ranges[i].start && appid <= user_ranges[i].end) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+// This provides an iterater for app_ids within the first user's app id's.
+static uid_t get_next_app_id(uid_t current_id) {
+  // If current_id is below the first of the user_ranges, then we're uninitialized, and return the
+  // first valid id.
+  if (current_id < user_ranges[0].start) {
+    return user_ranges[0].start;
+  }
+
+  uid_t incremented_id = current_id + 1;
+
+  // Check to see if our incremented_id is between two ranges, and if so, return the beginning of
+  // the next valid range.
+  for (size_t i = 1; i < arraysize(user_ranges); ++i) {
+    if (incremented_id > user_ranges[i - 1].end && incremented_id < user_ranges[i].start) {
+      return user_ranges[i].start;
+    }
+  }
+
+  // Check to see if our incremented_id is above final range, and return -1 to indicate that we've
+  // completed if so.
+  if (incremented_id > user_ranges[arraysize(user_ranges) - 1].end) {
+    return -1;
+  }
+
+  // Otherwise the incremented_id is valid, so return it.
+  return incremented_id;
+}
+
 // Translate a user/group name to the corresponding user/group id.
 // all_a1234 -> 0 * AID_USER_OFFSET + AID_SHARED_GID_START + 1234 (group name only)
 // u0_a1234_cache -> 0 * AID_USER_OFFSET + AID_CACHE_GID_START + 1234 (group name only)
@@ -377,7 +460,7 @@
 // AID_USER_OFFSET+                        -> u1_radio, u1_a1234, u2_i1234, etc.
 // returns a passwd structure (sets errno to ENOENT on failure).
 static passwd* app_id_to_passwd(uid_t uid, passwd_state_t* state) {
-  if (uid < AID_APP_START) {
+  if (uid < AID_APP_START || !is_valid_app_id(uid)) {
     errno = ENOENT;
     return NULL;
   }
@@ -405,7 +488,7 @@
 // Translate a gid into the corresponding app_<gid>
 // group structure (sets errno to ENOENT on failure).
 static group* app_id_to_group(gid_t gid, group_state_t* state) {
-  if (gid < AID_APP_START) {
+  if (gid < AID_APP_START || !is_valid_app_id(gid)) {
     errno = ENOENT;
     return NULL;
   }
@@ -521,15 +604,13 @@
         state->getpwent_idx++ - start + AID_OEM_RESERVED_2_START, state);
   }
 
-  start = end;
-  end += AID_USER_OFFSET - AID_APP_START; // Do not expose higher users
+  state->getpwent_idx = get_next_app_id(state->getpwent_idx);
 
-  if (state->getpwent_idx < end) {
-    return app_id_to_passwd(state->getpwent_idx++ - start + AID_APP_START, state);
+  if (state->getpwent_idx != -1) {
+    return app_id_to_passwd(state->getpwent_idx, state);
   }
 
   // We are not reporting u1_a* and higher or we will be here forever
-  state->getpwent_idx = -1;
   return NULL;
 }
 
@@ -652,12 +733,12 @@
   start = end;
   end += AID_USER_OFFSET - AID_APP_START; // Do not expose higher groups
 
-  if (state->getgrent_idx < end) {
-    init_group_state(state);
-    return app_id_to_group(state->getgrent_idx++ - start + AID_APP_START, state);
+  state->getgrent_idx = get_next_app_id(state->getgrent_idx);
+
+  if (state->getgrent_idx != -1) {
+    return app_id_to_group(state->getgrent_idx, state);
   }
 
   // We are not reporting u1_a* and higher or we will be here forever
-  state->getgrent_idx = -1;
   return NULL;
 }
diff --git a/libc/bionic/spawn.cpp b/libc/bionic/spawn.cpp
index 3588d02..061d68c 100644
--- a/libc/bionic/spawn.cpp
+++ b/libc/bionic/spawn.cpp
@@ -91,19 +91,13 @@
   sigset_t sigdefault;
 
   void Do() {
-    bool use_sigdefault = ((flags & POSIX_SPAWN_SETSIGDEF) != 0);
-
-    for (int s = 1; s < _NSIG; ++s) {
-      struct sigaction sa;
-      if (sigaction(s, nullptr, &sa) == -1) _exit(127);
-      if (sa.sa_handler == SIG_DFL) continue;
-      // POSIX: "Signals set to be caught by the calling process shall be set to the default
-      // action in the child process."
+    if ((flags & POSIX_SPAWN_SETSIGDEF) != 0) {
       // POSIX: "If POSIX_SPAWN_SETSIGDEF is set ... signals in sigdefault ... shall be set to
       // their default actions in the child process."
-      if (sa.sa_handler != SIG_IGN || (use_sigdefault && sigismember(&sigdefault, s))) {
-        sa.sa_handler = SIG_DFL;
-        if (sigaction(s, &sa, nullptr) == -1) _exit(127);
+      struct sigaction sa = {};
+      sa.sa_handler = SIG_DFL;
+      for (int s = 1; s < _NSIG; ++s) {
+        if (sigismember(&sigdefault, s) && sigaction(s, &sa, nullptr) == -1) _exit(127);
       }
     }
 
diff --git a/libc/bionic/sysconf.cpp b/libc/bionic/sysconf.cpp
index d45cb38..2442fd9 100644
--- a/libc/bionic/sysconf.cpp
+++ b/libc/bionic/sysconf.cpp
@@ -52,9 +52,16 @@
     // Things we actually have to calculate...
     //
     case _SC_ARG_MAX:
-      // Not a constant since Linux 2.6.23; see fs/exec.c for details.
-      // At least 32 pages, otherwise a quarter of the stack limit.
-      return MAX(__sysconf_rlimit(RLIMIT_STACK) / 4, _KERNEL_ARG_MAX);
+      // https://lkml.org/lkml/2017/11/15/813...
+      //
+      // I suspect a 128kB sysconf(_SC_ARG_MAX) is the sanest bet, simply
+      // because of that "conservative is better than aggressive".
+      //
+      // Especially since _technically_ we're still limiting things to that
+      // 128kB due to the single-string limit.
+      //
+      //               Linus
+      return ARG_MAX;
 
     case _SC_AVPHYS_PAGES:      return get_avphys_pages();
     case _SC_CHILD_MAX:         return __sysconf_rlimit(RLIMIT_NPROC);
diff --git a/libc/bionic/system_properties.cpp b/libc/bionic/system_properties.cpp
deleted file mode 100644
index 1a7a359..0000000
--- a/libc/bionic/system_properties.cpp
+++ /dev/null
@@ -1,1574 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <poll.h>
-#include <stdatomic.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <new>
-
-#include <linux/xattr.h>
-#include <netinet/in.h>
-#include <sys/mman.h>
-#include <sys/select.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <sys/un.h>
-#include <sys/xattr.h>
-
-#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
-#include <sys/_system_properties.h>
-#include <sys/system_properties.h>
-
-#include <async_safe/log.h>
-
-#include "private/ErrnoRestorer.h"
-#include "private/bionic_defs.h"
-#include "private/bionic_futex.h"
-#include "private/bionic_lock.h"
-#include "private/bionic_macros.h"
-#include "private/bionic_sdk_version.h"
-
-static constexpr int PROP_FILENAME_MAX = 1024;
-
-static constexpr uint32_t PROP_AREA_MAGIC = 0x504f5250;
-static constexpr uint32_t PROP_AREA_VERSION = 0xfc6ed0ab;
-
-static constexpr size_t PA_SIZE = 128 * 1024;
-
-#define SERIAL_DIRTY(serial) ((serial)&1)
-#define SERIAL_VALUE_LEN(serial) ((serial) >> 24)
-
-constexpr static const char kLongLegacyError[] = "Must use __system_property_read_callback() to read";
-
-// The error message fits in part of a union with the previous 92 char property value so there must
-// be room left over after the error message for the offset to the new longer property value and
-// future expansion fields if needed.
-// Note that this value cannot ever increase.  The offset to the new longer property value appears
-// immediately after it, so an increase of this size will break compatibility.
-constexpr size_t kLongLegacyErrorBufferSize = 56;
-static_assert(sizeof(kLongLegacyError) < kLongLegacyErrorBufferSize,
-              "Error message for long properties read by legacy libc must fit within 56 chars");
-
-static const char property_service_socket[] = "/dev/socket/" PROP_SERVICE_NAME;
-static const char* kServiceVersionPropertyName = "ro.property_service.version";
-
-// The C11 standard doesn't allow atomic loads from const fields,
-// though C++11 does.  Fudge it until standards get straightened out.
-static inline uint_least32_t load_const_atomic(const atomic_uint_least32_t* s, memory_order mo) {
-  atomic_uint_least32_t* non_const_s = const_cast<atomic_uint_least32_t*>(s);
-  return atomic_load_explicit(non_const_s, mo);
-}
-
-/*
- * Properties are stored in a hybrid trie/binary tree structure.
- * Each property's name is delimited at '.' characters, and the tokens are put
- * into a trie structure.  Siblings at each level of the trie are stored in a
- * binary tree.  For instance, "ro.secure"="1" could be stored as follows:
- *
- * +-----+   children    +----+   children    +--------+
- * |     |-------------->| ro |-------------->| secure |
- * +-----+               +----+               +--------+
- *                       /    \                /   |
- *                 left /      \ right   left /    |  prop   +===========+
- *                     v        v            v     +-------->| ro.secure |
- *                  +-----+   +-----+     +-----+            +-----------+
- *                  | net |   | sys |     | com |            |     1     |
- *                  +-----+   +-----+     +-----+            +===========+
- */
-
-// Represents a node in the trie.
-struct prop_bt {
-  uint32_t namelen;
-
-  // The property trie is updated only by the init process (single threaded) which provides
-  // property service. And it can be read by multiple threads at the same time.
-  // As the property trie is not protected by locks, we use atomic_uint_least32_t types for the
-  // left, right, children "pointers" in the trie node. To make sure readers who see the
-  // change of "pointers" can also notice the change of prop_bt structure contents pointed by
-  // the "pointers", we always use release-consume ordering pair when accessing these "pointers".
-
-  // prop "points" to prop_info structure if there is a propery associated with the trie node.
-  // Its situation is similar to the left, right, children "pointers". So we use
-  // atomic_uint_least32_t and release-consume ordering to protect it as well.
-
-  // We should also avoid rereading these fields redundantly, since not
-  // all processor implementations ensure that multiple loads from the
-  // same field are carried out in the right order.
-  atomic_uint_least32_t prop;
-
-  atomic_uint_least32_t left;
-  atomic_uint_least32_t right;
-
-  atomic_uint_least32_t children;
-
-  char name[0];
-
-  prop_bt(const char* name, const uint32_t name_length) {
-    this->namelen = name_length;
-    memcpy(this->name, name, name_length);
-    this->name[name_length] = '\0';
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(prop_bt);
-};
-
-class prop_area {
- public:
-  prop_area(const uint32_t magic, const uint32_t version) : magic_(magic), version_(version) {
-    atomic_init(&serial_, 0);
-    memset(reserved_, 0, sizeof(reserved_));
-    // Allocate enough space for the root node.
-    bytes_used_ = sizeof(prop_bt);
-  }
-
-  const prop_info* find(const char* name);
-  bool add(const char* name, unsigned int namelen, const char* value, unsigned int valuelen);
-
-  bool foreach (void (*propfn)(const prop_info* pi, void* cookie), void* cookie);
-
-  atomic_uint_least32_t* serial() {
-    return &serial_;
-  }
-  uint32_t magic() const {
-    return magic_;
-  }
-  uint32_t version() const {
-    return version_;
-  }
-
- private:
-  void* allocate_obj(const size_t size, uint_least32_t* const off);
-  prop_bt* new_prop_bt(const char* name, uint32_t namelen, uint_least32_t* const off);
-  prop_info* new_prop_info(const char* name, uint32_t namelen, const char* value, uint32_t valuelen,
-                           uint_least32_t* const off);
-  void* to_prop_obj(uint_least32_t off);
-  prop_bt* to_prop_bt(atomic_uint_least32_t* off_p);
-  prop_info* to_prop_info(atomic_uint_least32_t* off_p);
-
-  prop_bt* root_node();
-
-  prop_bt* find_prop_bt(prop_bt* const bt, const char* name, uint32_t namelen, bool alloc_if_needed);
-
-  const prop_info* find_property(prop_bt* const trie, const char* name, uint32_t namelen,
-                                 const char* value, uint32_t valuelen, bool alloc_if_needed);
-
-  bool foreach_property(prop_bt* const trie, void (*propfn)(const prop_info* pi, void* cookie),
-                        void* cookie);
-
-  uint32_t bytes_used_;
-  atomic_uint_least32_t serial_;
-  uint32_t magic_;
-  uint32_t version_;
-  uint32_t reserved_[28];
-  char data_[0];
-
-  DISALLOW_COPY_AND_ASSIGN(prop_area);
-};
-
-struct prop_info {
-  // Read only properties will not set anything but the bottom most bit of serial and the top byte.
-  // We borrow the 2nd from the top byte for extra flags, and use the bottom most bit of that for
-  // our first user, kLongFlag.
-  constexpr static uint32_t kLongFlag = 1 << 16;
-  atomic_uint_least32_t serial;
-  // we need to keep this buffer around because the property
-  // value can be modified whereas name is constant.
-  union {
-    char value[PROP_VALUE_MAX];
-    struct {
-      char error_message[kLongLegacyErrorBufferSize];
-      uint32_t offset;
-    } long_property;
-  };
-  char name[0];
-
-  bool is_long() const {
-    return (load_const_atomic(&serial, memory_order_relaxed) & kLongFlag) != 0;
-  }
-
-  const char* long_value() const {
-    // We can't store pointers here since this is shared memory that will have different absolute
-    // pointers in different processes.  We don't have data_ from prop_area, but since we know
-    // `this` is data_ + some offset and long_value is data_ + some other offset, we calculate the
-    // offset from `this` to long_value and store it as long_property.offset.
-    return reinterpret_cast<const char*>(this) + long_property.offset;
-  }
-
-  prop_info(const char* name, uint32_t namelen, const char* value, uint32_t valuelen) {
-    memcpy(this->name, name, namelen);
-    this->name[namelen] = '\0';
-    atomic_init(&this->serial, valuelen << 24);
-    memcpy(this->value, value, valuelen);
-    this->value[valuelen] = '\0';
-  }
-
-  prop_info(const char* name, uint32_t namelen, uint32_t long_offset) {
-    memcpy(this->name, name, namelen);
-    this->name[namelen] = '\0';
-
-    auto error_value_len = sizeof(kLongLegacyError) - 1;
-    atomic_init(&this->serial, error_value_len << 24 | kLongFlag);
-    memcpy(this->long_property.error_message, kLongLegacyError, sizeof(kLongLegacyError));
-
-    this->long_property.offset = long_offset;
-  }
-
- private:
-  DISALLOW_IMPLICIT_CONSTRUCTORS(prop_info);
-};
-
-static_assert(sizeof(prop_info) == 96, "size of struct prop_info must be 96 bytes");
-
-// This is public because it was exposed in the NDK. As of 2017-01, ~60 apps reference this symbol.
-__BIONIC_WEAK_VARIABLE_FOR_NATIVE_BRIDGE
-prop_area* __system_property_area__ = nullptr;
-
-static char property_filename[PROP_FILENAME_MAX] = PROP_FILENAME;
-static size_t pa_data_size;
-static size_t pa_size;
-static bool initialized = false;
-
-static prop_area* map_prop_area_rw(const char* filename, const char* context,
-                                   bool* fsetxattr_failed) {
-  /* dev is a tmpfs that we can use to carve a shared workspace
-   * out of, so let's do that...
-   */
-  const int fd = open(filename, O_RDWR | O_CREAT | O_NOFOLLOW | O_CLOEXEC | O_EXCL, 0444);
-
-  if (fd < 0) {
-    if (errno == EACCES) {
-      /* for consistency with the case where the process has already
-       * mapped the page in and segfaults when trying to write to it
-       */
-      abort();
-    }
-    return nullptr;
-  }
-
-  if (context) {
-    if (fsetxattr(fd, XATTR_NAME_SELINUX, context, strlen(context) + 1, 0) != 0) {
-      async_safe_format_log(ANDROID_LOG_ERROR, "libc",
-                            "fsetxattr failed to set context (%s) for \"%s\"", context, filename);
-      /*
-       * fsetxattr() will fail during system properties tests due to selinux policy.
-       * We do not want to create a custom policy for the tester, so we will continue in
-       * this function but set a flag that an error has occurred.
-       * Init, which is the only daemon that should ever call this function will abort
-       * when this error occurs.
-       * Otherwise, the tester will ignore it and continue, albeit without any selinux
-       * property separation.
-       */
-      if (fsetxattr_failed) {
-        *fsetxattr_failed = true;
-      }
-    }
-  }
-
-  if (ftruncate(fd, PA_SIZE) < 0) {
-    close(fd);
-    return nullptr;
-  }
-
-  pa_size = PA_SIZE;
-  pa_data_size = pa_size - sizeof(prop_area);
-
-  void* const memory_area = mmap(nullptr, pa_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
-  if (memory_area == MAP_FAILED) {
-    close(fd);
-    return nullptr;
-  }
-
-  prop_area* pa = new (memory_area) prop_area(PROP_AREA_MAGIC, PROP_AREA_VERSION);
-
-  close(fd);
-  return pa;
-}
-
-static prop_area* map_fd_ro(const int fd) {
-  struct stat fd_stat;
-  if (fstat(fd, &fd_stat) < 0) {
-    return nullptr;
-  }
-
-  if ((fd_stat.st_uid != 0) || (fd_stat.st_gid != 0) ||
-      ((fd_stat.st_mode & (S_IWGRP | S_IWOTH)) != 0) ||
-      (fd_stat.st_size < static_cast<off_t>(sizeof(prop_area)))) {
-    return nullptr;
-  }
-
-  pa_size = fd_stat.st_size;
-  pa_data_size = pa_size - sizeof(prop_area);
-
-  void* const map_result = mmap(nullptr, pa_size, PROT_READ, MAP_SHARED, fd, 0);
-  if (map_result == MAP_FAILED) {
-    return nullptr;
-  }
-
-  prop_area* pa = reinterpret_cast<prop_area*>(map_result);
-  if ((pa->magic() != PROP_AREA_MAGIC) || (pa->version() != PROP_AREA_VERSION)) {
-    munmap(pa, pa_size);
-    return nullptr;
-  }
-
-  return pa;
-}
-
-static prop_area* map_prop_area(const char* filename) {
-  int fd = open(filename, O_CLOEXEC | O_NOFOLLOW | O_RDONLY);
-  if (fd == -1) return nullptr;
-
-  prop_area* map_result = map_fd_ro(fd);
-  close(fd);
-
-  return map_result;
-}
-
-void* prop_area::allocate_obj(const size_t size, uint_least32_t* const off) {
-  const size_t aligned = __BIONIC_ALIGN(size, sizeof(uint_least32_t));
-  if (bytes_used_ + aligned > pa_data_size) {
-    return nullptr;
-  }
-
-  *off = bytes_used_;
-  bytes_used_ += aligned;
-  return data_ + *off;
-}
-
-prop_bt* prop_area::new_prop_bt(const char* name, uint32_t namelen, uint_least32_t* const off) {
-  uint_least32_t new_offset;
-  void* const p = allocate_obj(sizeof(prop_bt) + namelen + 1, &new_offset);
-  if (p != nullptr) {
-    prop_bt* bt = new (p) prop_bt(name, namelen);
-    *off = new_offset;
-    return bt;
-  }
-
-  return nullptr;
-}
-
-prop_info* prop_area::new_prop_info(const char* name, uint32_t namelen, const char* value,
-                                    uint32_t valuelen, uint_least32_t* const off) {
-  uint_least32_t new_offset;
-  void* const p = allocate_obj(sizeof(prop_info) + namelen + 1, &new_offset);
-  if (p == nullptr) return nullptr;
-
-  prop_info* info;
-  if (valuelen >= PROP_VALUE_MAX) {
-    uint32_t long_value_offset = 0;
-    char* long_location = reinterpret_cast<char*>(allocate_obj(valuelen + 1, &long_value_offset));
-    if (!long_location) return nullptr;
-
-    memcpy(long_location, value, valuelen);
-    long_location[valuelen] = '\0';
-
-    // Both new_offset and long_value_offset are offsets based off of data_, however prop_info
-    // does not know what data_ is, so we change this offset to be an offset from the prop_info
-    // pointer that contains it.
-    long_value_offset -= new_offset;
-
-    info = new (p) prop_info(name, namelen, long_value_offset);
-  } else {
-    info = new (p) prop_info(name, namelen, value, valuelen);
-  }
-  *off = new_offset;
-  return info;
-}
-
-void* prop_area::to_prop_obj(uint_least32_t off) {
-  if (off > pa_data_size) return nullptr;
-
-  return (data_ + off);
-}
-
-inline prop_bt* prop_area::to_prop_bt(atomic_uint_least32_t* off_p) {
-  uint_least32_t off = atomic_load_explicit(off_p, memory_order_consume);
-  return reinterpret_cast<prop_bt*>(to_prop_obj(off));
-}
-
-inline prop_info* prop_area::to_prop_info(atomic_uint_least32_t* off_p) {
-  uint_least32_t off = atomic_load_explicit(off_p, memory_order_consume);
-  return reinterpret_cast<prop_info*>(to_prop_obj(off));
-}
-
-inline prop_bt* prop_area::root_node() {
-  return reinterpret_cast<prop_bt*>(to_prop_obj(0));
-}
-
-static int cmp_prop_name(const char* one, uint32_t one_len, const char* two, uint32_t two_len) {
-  if (one_len < two_len)
-    return -1;
-  else if (one_len > two_len)
-    return 1;
-  else
-    return strncmp(one, two, one_len);
-}
-
-prop_bt* prop_area::find_prop_bt(prop_bt* const bt, const char* name, uint32_t namelen,
-                                 bool alloc_if_needed) {
-  prop_bt* current = bt;
-  while (true) {
-    if (!current) {
-      return nullptr;
-    }
-
-    const int ret = cmp_prop_name(name, namelen, current->name, current->namelen);
-    if (ret == 0) {
-      return current;
-    }
-
-    if (ret < 0) {
-      uint_least32_t left_offset = atomic_load_explicit(&current->left, memory_order_relaxed);
-      if (left_offset != 0) {
-        current = to_prop_bt(&current->left);
-      } else {
-        if (!alloc_if_needed) {
-          return nullptr;
-        }
-
-        uint_least32_t new_offset;
-        prop_bt* new_bt = new_prop_bt(name, namelen, &new_offset);
-        if (new_bt) {
-          atomic_store_explicit(&current->left, new_offset, memory_order_release);
-        }
-        return new_bt;
-      }
-    } else {
-      uint_least32_t right_offset = atomic_load_explicit(&current->right, memory_order_relaxed);
-      if (right_offset != 0) {
-        current = to_prop_bt(&current->right);
-      } else {
-        if (!alloc_if_needed) {
-          return nullptr;
-        }
-
-        uint_least32_t new_offset;
-        prop_bt* new_bt = new_prop_bt(name, namelen, &new_offset);
-        if (new_bt) {
-          atomic_store_explicit(&current->right, new_offset, memory_order_release);
-        }
-        return new_bt;
-      }
-    }
-  }
-}
-
-const prop_info* prop_area::find_property(prop_bt* const trie, const char* name, uint32_t namelen,
-                                          const char* value, uint32_t valuelen,
-                                          bool alloc_if_needed) {
-  if (!trie) return nullptr;
-
-  const char* remaining_name = name;
-  prop_bt* current = trie;
-  while (true) {
-    const char* sep = strchr(remaining_name, '.');
-    const bool want_subtree = (sep != nullptr);
-    const uint32_t substr_size = (want_subtree) ? sep - remaining_name : strlen(remaining_name);
-
-    if (!substr_size) {
-      return nullptr;
-    }
-
-    prop_bt* root = nullptr;
-    uint_least32_t children_offset = atomic_load_explicit(&current->children, memory_order_relaxed);
-    if (children_offset != 0) {
-      root = to_prop_bt(&current->children);
-    } else if (alloc_if_needed) {
-      uint_least32_t new_offset;
-      root = new_prop_bt(remaining_name, substr_size, &new_offset);
-      if (root) {
-        atomic_store_explicit(&current->children, new_offset, memory_order_release);
-      }
-    }
-
-    if (!root) {
-      return nullptr;
-    }
-
-    current = find_prop_bt(root, remaining_name, substr_size, alloc_if_needed);
-    if (!current) {
-      return nullptr;
-    }
-
-    if (!want_subtree) break;
-
-    remaining_name = sep + 1;
-  }
-
-  uint_least32_t prop_offset = atomic_load_explicit(&current->prop, memory_order_relaxed);
-  if (prop_offset != 0) {
-    return to_prop_info(&current->prop);
-  } else if (alloc_if_needed) {
-    uint_least32_t new_offset;
-    prop_info* new_info = new_prop_info(name, namelen, value, valuelen, &new_offset);
-    if (new_info) {
-      atomic_store_explicit(&current->prop, new_offset, memory_order_release);
-    }
-
-    return new_info;
-  } else {
-    return nullptr;
-  }
-}
-
-class PropertyServiceConnection {
- public:
-  PropertyServiceConnection() : last_error_(0) {
-    socket_ = ::socket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
-    if (socket_ == -1) {
-      last_error_ = errno;
-      return;
-    }
-
-    const size_t namelen = strlen(property_service_socket);
-    sockaddr_un addr;
-    memset(&addr, 0, sizeof(addr));
-    strlcpy(addr.sun_path, property_service_socket, sizeof(addr.sun_path));
-    addr.sun_family = AF_LOCAL;
-    socklen_t alen = namelen + offsetof(sockaddr_un, sun_path) + 1;
-
-    if (TEMP_FAILURE_RETRY(connect(socket_, reinterpret_cast<sockaddr*>(&addr), alen)) == -1) {
-      last_error_ = errno;
-      close(socket_);
-      socket_ = -1;
-    }
-  }
-
-  bool IsValid() {
-    return socket_ != -1;
-  }
-
-  int GetLastError() {
-    return last_error_;
-  }
-
-  bool RecvInt32(int32_t* value) {
-    int result = TEMP_FAILURE_RETRY(recv(socket_, value, sizeof(*value), MSG_WAITALL));
-    return CheckSendRecvResult(result, sizeof(*value));
-  }
-
-  int socket() {
-    return socket_;
-  }
-
-  ~PropertyServiceConnection() {
-    if (socket_ != -1) {
-      close(socket_);
-    }
-  }
-
- private:
-  bool CheckSendRecvResult(int result, int expected_len) {
-    if (result == -1) {
-      last_error_ = errno;
-    } else if (result != expected_len) {
-      last_error_ = -1;
-    } else {
-      last_error_ = 0;
-    }
-
-    return last_error_ == 0;
-  }
-
-  int socket_;
-  int last_error_;
-
-  friend class SocketWriter;
-};
-
-class SocketWriter {
- public:
-  explicit SocketWriter(PropertyServiceConnection* connection)
-      : connection_(connection), iov_index_(0), uint_buf_index_(0)
-  {}
-
-  SocketWriter& WriteUint32(uint32_t value) {
-    CHECK(uint_buf_index_ < kUintBufSize);
-    CHECK(iov_index_ < kIovSize);
-    uint32_t* ptr = uint_buf_ + uint_buf_index_;
-    uint_buf_[uint_buf_index_++] = value;
-    iov_[iov_index_].iov_base = ptr;
-    iov_[iov_index_].iov_len = sizeof(*ptr);
-    ++iov_index_;
-    return *this;
-  }
-
-  SocketWriter& WriteString(const char* value) {
-    uint32_t valuelen = strlen(value);
-    WriteUint32(valuelen);
-    if (valuelen == 0) {
-      return *this;
-    }
-
-    CHECK(iov_index_ < kIovSize);
-    iov_[iov_index_].iov_base = const_cast<char*>(value);
-    iov_[iov_index_].iov_len = valuelen;
-    ++iov_index_;
-
-    return *this;
-  }
-
-  bool Send() {
-    if (!connection_->IsValid()) {
-      return false;
-    }
-
-    if (writev(connection_->socket(), iov_, iov_index_) == -1) {
-      connection_->last_error_ = errno;
-      return false;
-    }
-
-    iov_index_ = uint_buf_index_ = 0;
-    return true;
-  }
-
- private:
-  static constexpr size_t kUintBufSize = 8;
-  static constexpr size_t kIovSize = 8;
-
-  PropertyServiceConnection* connection_;
-  iovec iov_[kIovSize];
-  size_t iov_index_;
-  uint32_t uint_buf_[kUintBufSize];
-  size_t uint_buf_index_;
-
-  DISALLOW_IMPLICIT_CONSTRUCTORS(SocketWriter);
-};
-
-struct prop_msg {
-  unsigned cmd;
-  char name[PROP_NAME_MAX];
-  char value[PROP_VALUE_MAX];
-};
-
-static int send_prop_msg(const prop_msg* msg) {
-  PropertyServiceConnection connection;
-  if (!connection.IsValid()) {
-    return connection.GetLastError();
-  }
-
-  int result = -1;
-  int s = connection.socket();
-
-  const int num_bytes = TEMP_FAILURE_RETRY(send(s, msg, sizeof(prop_msg), 0));
-  if (num_bytes == sizeof(prop_msg)) {
-    // We successfully wrote to the property server but now we
-    // wait for the property server to finish its work.  It
-    // acknowledges its completion by closing the socket so we
-    // poll here (on nothing), waiting for the socket to close.
-    // If you 'adb shell setprop foo bar' you'll see the POLLHUP
-    // once the socket closes.  Out of paranoia we cap our poll
-    // at 250 ms.
-    pollfd pollfds[1];
-    pollfds[0].fd = s;
-    pollfds[0].events = 0;
-    const int poll_result = TEMP_FAILURE_RETRY(poll(pollfds, 1, 250 /* ms */));
-    if (poll_result == 1 && (pollfds[0].revents & POLLHUP) != 0) {
-      result = 0;
-    } else {
-      // Ignore the timeout and treat it like a success anyway.
-      // The init process is single-threaded and its property
-      // service is sometimes slow to respond (perhaps it's off
-      // starting a child process or something) and thus this
-      // times out and the caller thinks it failed, even though
-      // it's still getting around to it.  So we fake it here,
-      // mostly for ctl.* properties, but we do try and wait 250
-      // ms so callers who do read-after-write can reliably see
-      // what they've written.  Most of the time.
-      // TODO: fix the system properties design.
-      async_safe_format_log(ANDROID_LOG_WARN, "libc",
-                            "Property service has timed out while trying to set \"%s\" to \"%s\"",
-                            msg->name, msg->value);
-      result = 0;
-    }
-  }
-
-  return result;
-}
-
-bool prop_area::foreach_property(prop_bt* const trie,
-                                 void (*propfn)(const prop_info* pi, void* cookie), void* cookie) {
-  if (!trie) return false;
-
-  uint_least32_t left_offset = atomic_load_explicit(&trie->left, memory_order_relaxed);
-  if (left_offset != 0) {
-    const int err = foreach_property(to_prop_bt(&trie->left), propfn, cookie);
-    if (err < 0) return false;
-  }
-  uint_least32_t prop_offset = atomic_load_explicit(&trie->prop, memory_order_relaxed);
-  if (prop_offset != 0) {
-    prop_info* info = to_prop_info(&trie->prop);
-    if (!info) return false;
-    propfn(info, cookie);
-  }
-  uint_least32_t children_offset = atomic_load_explicit(&trie->children, memory_order_relaxed);
-  if (children_offset != 0) {
-    const int err = foreach_property(to_prop_bt(&trie->children), propfn, cookie);
-    if (err < 0) return false;
-  }
-  uint_least32_t right_offset = atomic_load_explicit(&trie->right, memory_order_relaxed);
-  if (right_offset != 0) {
-    const int err = foreach_property(to_prop_bt(&trie->right), propfn, cookie);
-    if (err < 0) return false;
-  }
-
-  return true;
-}
-
-const prop_info* prop_area::find(const char* name) {
-  return find_property(root_node(), name, strlen(name), nullptr, 0, false);
-}
-
-bool prop_area::add(const char* name, unsigned int namelen, const char* value,
-                    unsigned int valuelen) {
-  return find_property(root_node(), name, namelen, value, valuelen, true);
-}
-
-bool prop_area::foreach (void (*propfn)(const prop_info* pi, void* cookie), void* cookie) {
-  return foreach_property(root_node(), propfn, cookie);
-}
-
-class context_node {
- public:
-  context_node(context_node* next, const char* context, prop_area* pa)
-      : next(next), context_(strdup(context)), pa_(pa), no_access_(false) {
-    lock_.init(false);
-  }
-  ~context_node() {
-    unmap();
-    free(context_);
-  }
-  bool open(bool access_rw, bool* fsetxattr_failed);
-  bool check_access_and_open();
-  void reset_access();
-
-  const char* context() const {
-    return context_;
-  }
-  prop_area* pa() {
-    return pa_;
-  }
-
-  context_node* next;
-
- private:
-  bool check_access();
-  void unmap();
-
-  Lock lock_;
-  char* context_;
-  prop_area* pa_;
-  bool no_access_;
-};
-
-struct prefix_node {
-  prefix_node(struct prefix_node* next, const char* prefix, context_node* context)
-      : prefix(strdup(prefix)), prefix_len(strlen(prefix)), context(context), next(next) {
-  }
-  ~prefix_node() {
-    free(prefix);
-  }
-  char* prefix;
-  const size_t prefix_len;
-  context_node* context;
-  struct prefix_node* next;
-};
-
-template <typename List, typename... Args>
-static inline void list_add(List** list, Args... args) {
-  *list = new List(*list, args...);
-}
-
-static void list_add_after_len(prefix_node** list, const char* prefix, context_node* context) {
-  size_t prefix_len = strlen(prefix);
-
-  auto next_list = list;
-
-  while (*next_list) {
-    if ((*next_list)->prefix_len < prefix_len || (*next_list)->prefix[0] == '*') {
-      list_add(next_list, prefix, context);
-      return;
-    }
-    next_list = &(*next_list)->next;
-  }
-  list_add(next_list, prefix, context);
-}
-
-template <typename List, typename Func>
-static void list_foreach(List* list, Func func) {
-  while (list) {
-    func(list);
-    list = list->next;
-  }
-}
-
-template <typename List, typename Func>
-static List* list_find(List* list, Func func) {
-  while (list) {
-    if (func(list)) {
-      return list;
-    }
-    list = list->next;
-  }
-  return nullptr;
-}
-
-template <typename List>
-static void list_free(List** list) {
-  while (*list) {
-    auto old_list = *list;
-    *list = old_list->next;
-    delete old_list;
-  }
-}
-
-static prefix_node* prefixes = nullptr;
-static context_node* contexts = nullptr;
-
-/*
- * pthread_mutex_lock() calls into system_properties in the case of contention.
- * This creates a risk of dead lock if any system_properties functions
- * use pthread locks after system_property initialization.
- *
- * For this reason, the below three functions use a bionic Lock and static
- * allocation of memory for each filename.
- */
-
-bool context_node::open(bool access_rw, bool* fsetxattr_failed) {
-  lock_.lock();
-  if (pa_) {
-    lock_.unlock();
-    return true;
-  }
-
-  char filename[PROP_FILENAME_MAX];
-  int len = async_safe_format_buffer(filename, sizeof(filename), "%s/%s", property_filename,
-                                     context_);
-  if (len < 0 || len > PROP_FILENAME_MAX) {
-    lock_.unlock();
-    return false;
-  }
-
-  if (access_rw) {
-    pa_ = map_prop_area_rw(filename, context_, fsetxattr_failed);
-  } else {
-    pa_ = map_prop_area(filename);
-  }
-  lock_.unlock();
-  return pa_;
-}
-
-bool context_node::check_access_and_open() {
-  if (!pa_ && !no_access_) {
-    if (!check_access() || !open(false, nullptr)) {
-      no_access_ = true;
-    }
-  }
-  return pa_;
-}
-
-void context_node::reset_access() {
-  if (!check_access()) {
-    unmap();
-    no_access_ = true;
-  } else {
-    no_access_ = false;
-  }
-}
-
-bool context_node::check_access() {
-  char filename[PROP_FILENAME_MAX];
-  int len = async_safe_format_buffer(filename, sizeof(filename), "%s/%s", property_filename,
-                                     context_);
-  if (len < 0 || len > PROP_FILENAME_MAX) {
-    return false;
-  }
-
-  return access(filename, R_OK) == 0;
-}
-
-void context_node::unmap() {
-  if (!pa_) {
-    return;
-  }
-
-  munmap(pa_, pa_size);
-  if (pa_ == __system_property_area__) {
-    __system_property_area__ = nullptr;
-  }
-  pa_ = nullptr;
-}
-
-static bool map_system_property_area(bool access_rw, bool* fsetxattr_failed) {
-  char filename[PROP_FILENAME_MAX];
-  int len =
-      async_safe_format_buffer(filename, sizeof(filename), "%s/properties_serial",
-                               property_filename);
-  if (len < 0 || len > PROP_FILENAME_MAX) {
-    __system_property_area__ = nullptr;
-    return false;
-  }
-
-  if (access_rw) {
-    __system_property_area__ =
-        map_prop_area_rw(filename, "u:object_r:properties_serial:s0", fsetxattr_failed);
-  } else {
-    __system_property_area__ = map_prop_area(filename);
-  }
-  return __system_property_area__;
-}
-
-static prop_area* get_prop_area_for_name(const char* name) {
-  auto entry = list_find(prefixes, [name](prefix_node* l) {
-    return l->prefix[0] == '*' || !strncmp(l->prefix, name, l->prefix_len);
-  });
-  if (!entry) {
-    return nullptr;
-  }
-
-  auto cnode = entry->context;
-  if (!cnode->pa()) {
-    /*
-     * We explicitly do not check no_access_ in this case because unlike the
-     * case of foreach(), we want to generate an selinux audit for each
-     * non-permitted property access in this function.
-     */
-    cnode->open(false, nullptr);
-  }
-  return cnode->pa();
-}
-
-/*
- * The below two functions are duplicated from label_support.c in libselinux.
- * TODO: Find a location suitable for these functions such that both libc and
- * libselinux can share a common source file.
- */
-
-/*
- * The read_spec_entries and read_spec_entry functions may be used to
- * replace sscanf to read entries from spec files. The file and
- * property services now use these.
- */
-
-/* Read an entry from a spec file (e.g. file_contexts) */
-static inline int read_spec_entry(char** entry, char** ptr, int* len) {
-  *entry = nullptr;
-  char* tmp_buf = nullptr;
-
-  while (isspace(**ptr) && **ptr != '\0') (*ptr)++;
-
-  tmp_buf = *ptr;
-  *len = 0;
-
-  while (!isspace(**ptr) && **ptr != '\0') {
-    (*ptr)++;
-    (*len)++;
-  }
-
-  if (*len) {
-    *entry = strndup(tmp_buf, *len);
-    if (!*entry) return -1;
-  }
-
-  return 0;
-}
-
-/*
- * line_buf - Buffer containing the spec entries .
- * num_args - The number of spec parameter entries to process.
- * ...      - A 'char **spec_entry' for each parameter.
- * returns  - The number of items processed.
- *
- * This function calls read_spec_entry() to do the actual string processing.
- */
-static int read_spec_entries(char* line_buf, int num_args, ...) {
-  char **spec_entry, *buf_p;
-  int len, rc, items, entry_len = 0;
-  va_list ap;
-
-  len = strlen(line_buf);
-  if (line_buf[len - 1] == '\n')
-    line_buf[len - 1] = '\0';
-  else
-    /* Handle case if line not \n terminated by bumping
-     * the len for the check below (as the line is NUL
-     * terminated by getline(3)) */
-    len++;
-
-  buf_p = line_buf;
-  while (isspace(*buf_p)) buf_p++;
-
-  /* Skip comment lines and empty lines. */
-  if (*buf_p == '#' || *buf_p == '\0') return 0;
-
-  /* Process the spec file entries */
-  va_start(ap, num_args);
-
-  items = 0;
-  while (items < num_args) {
-    spec_entry = va_arg(ap, char**);
-
-    if (len - 1 == buf_p - line_buf) {
-      va_end(ap);
-      return items;
-    }
-
-    rc = read_spec_entry(spec_entry, &buf_p, &entry_len);
-    if (rc < 0) {
-      va_end(ap);
-      return rc;
-    }
-    if (entry_len) items++;
-  }
-  va_end(ap);
-  return items;
-}
-
-static bool initialize_properties_from_file(const char* filename) {
-  FILE* file = fopen(filename, "re");
-  if (!file) {
-    return false;
-  }
-
-  char* buffer = nullptr;
-  size_t line_len;
-  char* prop_prefix = nullptr;
-  char* context = nullptr;
-
-  while (getline(&buffer, &line_len, file) > 0) {
-    int items = read_spec_entries(buffer, 2, &prop_prefix, &context);
-    if (items <= 0) {
-      continue;
-    }
-    if (items == 1) {
-      free(prop_prefix);
-      continue;
-    }
-    /*
-     * init uses ctl.* properties as an IPC mechanism and does not write them
-     * to a property file, therefore we do not need to create property files
-     * to store them.
-     */
-    if (!strncmp(prop_prefix, "ctl.", 4)) {
-      free(prop_prefix);
-      free(context);
-      continue;
-    }
-
-    auto old_context =
-        list_find(contexts, [context](context_node* l) { return !strcmp(l->context(), context); });
-    if (old_context) {
-      list_add_after_len(&prefixes, prop_prefix, old_context);
-    } else {
-      list_add(&contexts, context, nullptr);
-      list_add_after_len(&prefixes, prop_prefix, contexts);
-    }
-    free(prop_prefix);
-    free(context);
-  }
-
-  free(buffer);
-  fclose(file);
-
-  return true;
-}
-
-static bool initialize_properties() {
-  // If we do find /property_contexts, then this is being
-  // run as part of the OTA updater on older release that had
-  // /property_contexts - b/34370523
-  if (initialize_properties_from_file("/property_contexts")) {
-    return true;
-  }
-
-  // Use property_contexts from /system & /vendor, fall back to those from /
-  if (access("/system/etc/selinux/plat_property_contexts", R_OK) != -1) {
-    if (!initialize_properties_from_file("/system/etc/selinux/plat_property_contexts")) {
-      return false;
-    }
-    // Don't check for failure here, so we always have a sane list of properties.
-    // E.g. In case of recovery, the vendor partition will not have mounted and we
-    // still need the system / platform properties to function.
-    initialize_properties_from_file("/vendor/etc/selinux/nonplat_property_contexts");
-  } else {
-    if (!initialize_properties_from_file("/plat_property_contexts")) {
-      return false;
-    }
-    initialize_properties_from_file("/nonplat_property_contexts");
-  }
-
-  return true;
-}
-
-static bool is_dir(const char* pathname) {
-  struct stat info;
-  if (stat(pathname, &info) == -1) {
-    return false;
-  }
-  return S_ISDIR(info.st_mode);
-}
-
-static void free_and_unmap_contexts() {
-  list_free(&prefixes);
-  list_free(&contexts);
-  if (__system_property_area__) {
-    munmap(__system_property_area__, pa_size);
-    __system_property_area__ = nullptr;
-  }
-}
-
-__BIONIC_WEAK_FOR_NATIVE_BRIDGE
-int __system_properties_init() {
-  // This is called from __libc_init_common, and should leave errno at 0 (http://b/37248982).
-  ErrnoRestorer errno_restorer;
-
-  if (initialized) {
-    list_foreach(contexts, [](context_node* l) { l->reset_access(); });
-    return 0;
-  }
-  if (is_dir(property_filename)) {
-    if (!initialize_properties()) {
-      return -1;
-    }
-    if (!map_system_property_area(false, nullptr)) {
-      free_and_unmap_contexts();
-      return -1;
-    }
-  } else {
-    __system_property_area__ = map_prop_area(property_filename);
-    if (!__system_property_area__) {
-      return -1;
-    }
-    list_add(&contexts, "legacy_system_prop_area", __system_property_area__);
-    list_add_after_len(&prefixes, "*", contexts);
-  }
-  initialized = true;
-  return 0;
-}
-
-__BIONIC_WEAK_FOR_NATIVE_BRIDGE
-int __system_property_set_filename(const char* filename) {
-  size_t len = strlen(filename);
-  if (len >= sizeof(property_filename)) return -1;
-
-  strcpy(property_filename, filename);
-  return 0;
-}
-
-__BIONIC_WEAK_FOR_NATIVE_BRIDGE
-int __system_property_area_init() {
-  free_and_unmap_contexts();
-  mkdir(property_filename, S_IRWXU | S_IXGRP | S_IXOTH);
-  if (!initialize_properties()) {
-    return -1;
-  }
-  bool open_failed = false;
-  bool fsetxattr_failed = false;
-  list_foreach(contexts, [&fsetxattr_failed, &open_failed](context_node* l) {
-    if (!l->open(true, &fsetxattr_failed)) {
-      open_failed = true;
-    }
-  });
-  if (open_failed || !map_system_property_area(true, &fsetxattr_failed)) {
-    free_and_unmap_contexts();
-    return -1;
-  }
-  initialized = true;
-  return fsetxattr_failed ? -2 : 0;
-}
-
-__BIONIC_WEAK_FOR_NATIVE_BRIDGE
-uint32_t __system_property_area_serial() {
-  prop_area* pa = __system_property_area__;
-  if (!pa) {
-    return -1;
-  }
-  // Make sure this read fulfilled before __system_property_serial
-  return atomic_load_explicit(pa->serial(), memory_order_acquire);
-}
-
-__BIONIC_WEAK_FOR_NATIVE_BRIDGE
-const prop_info* __system_property_find(const char* name) {
-  if (!__system_property_area__) {
-    return nullptr;
-  }
-
-  prop_area* pa = get_prop_area_for_name(name);
-  if (!pa) {
-    async_safe_format_log(ANDROID_LOG_ERROR, "libc", "Access denied finding property \"%s\"", name);
-    return nullptr;
-  }
-
-  return pa->find(name);
-}
-
-static bool is_read_only(const char* name) {
-  return strncmp(name, "ro.", 3) == 0;
-}
-
-__BIONIC_WEAK_FOR_NATIVE_BRIDGE
-int __system_property_read(const prop_info* pi, char* name, char* value) {
-  while (true) {
-    uint32_t serial = __system_property_serial(pi);  // acquire semantics
-    size_t len = SERIAL_VALUE_LEN(serial);
-    memcpy(value, pi->value, len + 1);
-    // TODO: Fix the synchronization scheme here.
-    // There is no fully supported way to implement this kind
-    // of synchronization in C++11, since the memcpy races with
-    // updates to pi, and the data being accessed is not atomic.
-    // The following fence is unintuitive, but would be the
-    // correct one if memcpy used memory_order_relaxed atomic accesses.
-    // In practice it seems unlikely that the generated code would
-    // would be any different, so this should be OK.
-    atomic_thread_fence(memory_order_acquire);
-    if (serial == load_const_atomic(&(pi->serial), memory_order_relaxed)) {
-      if (name != nullptr) {
-        size_t namelen = strlcpy(name, pi->name, PROP_NAME_MAX);
-        if (namelen >= PROP_NAME_MAX) {
-          async_safe_format_log(ANDROID_LOG_ERROR, "libc",
-                                "The property name length for \"%s\" is >= %d;"
-                                " please use __system_property_read_callback"
-                                " to read this property. (the name is truncated to \"%s\")",
-                                pi->name, PROP_NAME_MAX - 1, name);
-        }
-      }
-      if (is_read_only(pi->name) && pi->is_long()) {
-        async_safe_format_log(ANDROID_LOG_ERROR, "libc",
-                              "The property \"%s\" has a value with length %zu that is too large for"
-                              " __system_property_get()/__system_property_read(); use"
-                              " __system_property_read_callback() instead.",
-                              pi->name, strlen(pi->long_value()));
-      }
-      return len;
-    }
-  }
-}
-
-__BIONIC_WEAK_FOR_NATIVE_BRIDGE
-void __system_property_read_callback(const prop_info* pi,
-                                     void (*callback)(void* cookie,
-                                                      const char* name,
-                                                      const char* value,
-                                                      uint32_t serial),
-                                     void* cookie) {
-  // Read only properties don't need to copy the value to a temporary buffer, since it can never
-  // change.
-  if (is_read_only(pi->name)) {
-    uint32_t serial = __system_property_serial(pi);
-    if (pi->is_long()) {
-      callback(cookie, pi->name, pi->long_value(), serial);
-    } else {
-      callback(cookie, pi->name, pi->value, serial);
-    }
-    return;
-  }
-
-  while (true) {
-    uint32_t serial = __system_property_serial(pi);  // acquire semantics
-    size_t len = SERIAL_VALUE_LEN(serial);
-    char value_buf[len + 1];
-
-    memcpy(value_buf, pi->value, len);
-    value_buf[len] = '\0';
-
-    // TODO: see todo in __system_property_read function
-    atomic_thread_fence(memory_order_acquire);
-    if (serial == load_const_atomic(&(pi->serial), memory_order_relaxed)) {
-      callback(cookie, pi->name, value_buf, serial);
-      return;
-    }
-  }
-}
-
-__BIONIC_WEAK_FOR_NATIVE_BRIDGE
-int __system_property_get(const char* name, char* value) {
-  const prop_info* pi = __system_property_find(name);
-
-  if (pi != 0) {
-    return __system_property_read(pi, nullptr, value);
-  } else {
-    value[0] = 0;
-    return 0;
-  }
-}
-
-static constexpr uint32_t kProtocolVersion1 = 1;
-static constexpr uint32_t kProtocolVersion2 = 2;  // current
-
-static atomic_uint_least32_t g_propservice_protocol_version = 0;
-
-static void detect_protocol_version() {
-  char value[PROP_VALUE_MAX];
-  if (__system_property_get(kServiceVersionPropertyName, value) == 0) {
-    g_propservice_protocol_version = kProtocolVersion1;
-    async_safe_format_log(ANDROID_LOG_WARN, "libc",
-                          "Using old property service protocol (\"%s\" is not set)",
-                          kServiceVersionPropertyName);
-  } else {
-    uint32_t version = static_cast<uint32_t>(atoll(value));
-    if (version >= kProtocolVersion2) {
-      g_propservice_protocol_version = kProtocolVersion2;
-    } else {
-      async_safe_format_log(ANDROID_LOG_WARN, "libc",
-                            "Using old property service protocol (\"%s\"=\"%s\")",
-                            kServiceVersionPropertyName, value);
-      g_propservice_protocol_version = kProtocolVersion1;
-    }
-  }
-}
-
-__BIONIC_WEAK_FOR_NATIVE_BRIDGE
-int __system_property_set(const char* key, const char* value) {
-  if (key == nullptr) return -1;
-  if (value == nullptr) value = "";
-
-  if (g_propservice_protocol_version == 0) {
-    detect_protocol_version();
-  }
-
-  if (g_propservice_protocol_version == kProtocolVersion1) {
-    // Old protocol does not support long names or values
-    if (strlen(key) >= PROP_NAME_MAX) return -1;
-    if (strlen(value) >= PROP_VALUE_MAX) return -1;
-
-    prop_msg msg;
-    memset(&msg, 0, sizeof msg);
-    msg.cmd = PROP_MSG_SETPROP;
-    strlcpy(msg.name, key, sizeof msg.name);
-    strlcpy(msg.value, value, sizeof msg.value);
-
-    return send_prop_msg(&msg);
-  } else {
-    // New protocol only allows long values for ro. properties only.
-    if (strlen(value) >= PROP_VALUE_MAX && !is_read_only(key)) return -1;
-    // Use proper protocol
-    PropertyServiceConnection connection;
-    if (!connection.IsValid()) {
-      errno = connection.GetLastError();
-      async_safe_format_log(ANDROID_LOG_WARN,
-                            "libc",
-                            "Unable to set property \"%s\" to \"%s\": connection failed; errno=%d (%s)",
-                            key,
-                            value,
-                            errno,
-                            strerror(errno));
-      return -1;
-    }
-
-    SocketWriter writer(&connection);
-    if (!writer.WriteUint32(PROP_MSG_SETPROP2).WriteString(key).WriteString(value).Send()) {
-      errno = connection.GetLastError();
-      async_safe_format_log(ANDROID_LOG_WARN,
-                            "libc",
-                            "Unable to set property \"%s\" to \"%s\": write failed; errno=%d (%s)",
-                            key,
-                            value,
-                            errno,
-                            strerror(errno));
-      return -1;
-    }
-
-    int result = -1;
-    if (!connection.RecvInt32(&result)) {
-      errno = connection.GetLastError();
-      async_safe_format_log(ANDROID_LOG_WARN,
-                            "libc",
-                            "Unable to set property \"%s\" to \"%s\": recv failed; errno=%d (%s)",
-                            key,
-                            value,
-                            errno,
-                            strerror(errno));
-      return -1;
-    }
-
-    if (result != PROP_SUCCESS) {
-      async_safe_format_log(ANDROID_LOG_WARN,
-                            "libc",
-                            "Unable to set property \"%s\" to \"%s\": error code: 0x%x",
-                            key,
-                            value,
-                            result);
-      return -1;
-    }
-
-    return 0;
-  }
-}
-
-__BIONIC_WEAK_FOR_NATIVE_BRIDGE
-int __system_property_update(prop_info* pi, const char* value, unsigned int len) {
-  if (len >= PROP_VALUE_MAX) {
-    return -1;
-  }
-
-  prop_area* pa = __system_property_area__;
-
-  if (!pa) {
-    return -1;
-  }
-
-  uint32_t serial = atomic_load_explicit(&pi->serial, memory_order_relaxed);
-  serial |= 1;
-  atomic_store_explicit(&pi->serial, serial, memory_order_relaxed);
-  // The memcpy call here also races.  Again pretend it
-  // used memory_order_relaxed atomics, and use the analogous
-  // counterintuitive fence.
-  atomic_thread_fence(memory_order_release);
-  strlcpy(pi->value, value, len + 1);
-
-  atomic_store_explicit(&pi->serial, (len << 24) | ((serial + 1) & 0xffffff), memory_order_release);
-  __futex_wake(&pi->serial, INT32_MAX);
-
-  atomic_store_explicit(pa->serial(), atomic_load_explicit(pa->serial(), memory_order_relaxed) + 1,
-                        memory_order_release);
-  __futex_wake(pa->serial(), INT32_MAX);
-
-  return 0;
-}
-
-__BIONIC_WEAK_FOR_NATIVE_BRIDGE
-int __system_property_add(const char* name, unsigned int namelen, const char* value,
-                          unsigned int valuelen) {
-  if (valuelen >= PROP_VALUE_MAX && !is_read_only(name)) {
-    return -1;
-  }
-
-  if (namelen < 1) {
-    return -1;
-  }
-
-  if (!__system_property_area__) {
-    return -1;
-  }
-
-  prop_area* pa = get_prop_area_for_name(name);
-
-  if (!pa) {
-    async_safe_format_log(ANDROID_LOG_ERROR, "libc", "Access denied adding property \"%s\"", name);
-    return -1;
-  }
-
-  bool ret = pa->add(name, namelen, value, valuelen);
-  if (!ret) {
-    return -1;
-  }
-
-  // There is only a single mutator, but we want to make sure that
-  // updates are visible to a reader waiting for the update.
-  atomic_store_explicit(
-      __system_property_area__->serial(),
-      atomic_load_explicit(__system_property_area__->serial(), memory_order_relaxed) + 1,
-      memory_order_release);
-  __futex_wake(__system_property_area__->serial(), INT32_MAX);
-  return 0;
-}
-
-// Wait for non-locked serial, and retrieve it with acquire semantics.
-__BIONIC_WEAK_FOR_NATIVE_BRIDGE
-uint32_t __system_property_serial(const prop_info* pi) {
-  uint32_t serial = load_const_atomic(&pi->serial, memory_order_acquire);
-  while (SERIAL_DIRTY(serial)) {
-    __futex_wait(const_cast<_Atomic(uint_least32_t)*>(&pi->serial), serial, nullptr);
-    serial = load_const_atomic(&pi->serial, memory_order_acquire);
-  }
-  return serial;
-}
-
-__BIONIC_WEAK_FOR_NATIVE_BRIDGE
-uint32_t __system_property_wait_any(uint32_t old_serial) {
-  uint32_t new_serial;
-  __system_property_wait(nullptr, old_serial, &new_serial, nullptr);
-  return new_serial;
-}
-
-__BIONIC_WEAK_FOR_NATIVE_BRIDGE
-bool __system_property_wait(const prop_info* pi,
-                            uint32_t old_serial,
-                            uint32_t* new_serial_ptr,
-                            const timespec* relative_timeout) {
-  // Are we waiting on the global serial or a specific serial?
-  atomic_uint_least32_t* serial_ptr;
-  if (pi == nullptr) {
-    if (__system_property_area__ == nullptr) return -1;
-    serial_ptr = __system_property_area__->serial();
-  } else {
-    serial_ptr = const_cast<atomic_uint_least32_t*>(&pi->serial);
-  }
-
-  uint32_t new_serial;
-  do {
-    int rc;
-    if ((rc = __futex_wait(serial_ptr, old_serial, relative_timeout)) != 0 && rc == -ETIMEDOUT) {
-      return false;
-    }
-    new_serial = load_const_atomic(serial_ptr, memory_order_acquire);
-  } while (new_serial == old_serial);
-
-  *new_serial_ptr = new_serial;
-  return true;
-}
-
-__BIONIC_WEAK_FOR_NATIVE_BRIDGE
-const prop_info* __system_property_find_nth(unsigned n) {
-  struct find_nth {
-    const uint32_t sought;
-    uint32_t current;
-    const prop_info* result;
-
-    explicit find_nth(uint32_t n) : sought(n), current(0), result(nullptr) {}
-    static void fn(const prop_info* pi, void* ptr) {
-      find_nth* self = reinterpret_cast<find_nth*>(ptr);
-      if (self->current++ == self->sought) self->result = pi;
-    }
-  } state(n);
-  __system_property_foreach(find_nth::fn, &state);
-  return state.result;
-}
-
-__BIONIC_WEAK_FOR_NATIVE_BRIDGE
-int __system_property_foreach(void (*propfn)(const prop_info* pi, void* cookie), void* cookie) {
-  if (!__system_property_area__) {
-    return -1;
-  }
-
-  list_foreach(contexts, [propfn, cookie](context_node* l) {
-    if (l->check_access_and_open()) {
-      l->pa()->foreach(propfn, cookie);
-    }
-  });
-  return 0;
-}
diff --git a/libc/kernel/tools/cpp.py b/libc/kernel/tools/cpp.py
index fff80f6..68144cd 100644
--- a/libc/kernel/tools/cpp.py
+++ b/libc/kernel/tools/cpp.py
@@ -27,7 +27,7 @@
 
 # Set up LD_LIBRARY_PATH to include libclang.so, libLLVM.so, and etc.
 # Note that setting LD_LIBRARY_PATH with os.putenv() sometimes doesn't help.
-clang.cindex.Config.set_library_path(os.path.join(top, 'prebuilts/sdk/tools/linux/lib64'))
+clang.cindex.Config.set_library_file(os.path.join(top, 'prebuilts/sdk/tools/linux/lib64/libclang_android.so'))
 
 from defaults import kCppUndefinedMacro
 from defaults import kernel_remove_config_macros
diff --git a/libc/kernel/tools/defaults.py b/libc/kernel/tools/defaults.py
index b0fb95f..1afdc77 100644
--- a/libc/kernel/tools/defaults.py
+++ b/libc/kernel/tools/defaults.py
@@ -58,8 +58,6 @@
 
 # Replace tokens in the output according to this mapping.
 kernel_token_replacements = {
-    # The kernel's ARG_MAX is actually the "minimum" maximum (see fs/exec.c).
-    "ARG_MAX": "_KERNEL_ARG_MAX",
     # The kernel usage of __unused for unused struct fields conflicts with the macro defined in <sys/cdefs.h>.
     "__unused": "__linux_unused",
     # The kernel usage of C++ keywords causes problems for C++ code so rename.
@@ -84,8 +82,6 @@
     "epoll_event": "__kernel_uapi_epoll_event",
     # This causes problems when trying to export the headers for the ndk.
     "__attribute_const__": "__attribute__((__const__))",
-    # There is a mismatch between upstream and our kernels for this structure.
-    "binder_fd_array_object": "__kernel_binder_fd_array_object",
     }
 
 # This is the set of known static inline functions that we want to keep
diff --git a/libc/kernel/uapi/asm-arm/asm/kvm.h b/libc/kernel/uapi/asm-arm/asm/kvm.h
index c814a09..2332ae2 100644
--- a/libc/kernel/uapi/asm-arm/asm/kvm.h
+++ b/libc/kernel/uapi/asm-arm/asm/kvm.h
@@ -147,6 +147,12 @@
 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK (0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)
 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK 0x3ff
 #define VGIC_LEVEL_INFO_LINE_LEVEL 0
+#define KVM_ARM_VCPU_PMU_V3_CTRL 0
+#define KVM_ARM_VCPU_PMU_V3_IRQ 0
+#define KVM_ARM_VCPU_PMU_V3_INIT 1
+#define KVM_ARM_VCPU_TIMER_CTRL 1
+#define KVM_ARM_VCPU_TIMER_IRQ_VTIMER 0
+#define KVM_ARM_VCPU_TIMER_IRQ_PTIMER 1
 #define KVM_DEV_ARM_VGIC_CTRL_INIT 0
 #define KVM_DEV_ARM_ITS_SAVE_TABLES 1
 #define KVM_DEV_ARM_ITS_RESTORE_TABLES 2
diff --git a/libc/kernel/uapi/asm-arm64/asm/hwcap.h b/libc/kernel/uapi/asm-arm64/asm/hwcap.h
index 4ab16ad..60b8305 100644
--- a/libc/kernel/uapi/asm-arm64/asm/hwcap.h
+++ b/libc/kernel/uapi/asm-arm64/asm/hwcap.h
@@ -34,4 +34,5 @@
 #define HWCAP_JSCVT (1 << 13)
 #define HWCAP_FCMA (1 << 14)
 #define HWCAP_LRCPC (1 << 15)
+#define HWCAP_DCPOP (1 << 16)
 #endif
diff --git a/libc/kernel/uapi/asm-arm64/asm/kvm.h b/libc/kernel/uapi/asm-arm64/asm/kvm.h
index dade888..a68a8a2 100644
--- a/libc/kernel/uapi/asm-arm64/asm/kvm.h
+++ b/libc/kernel/uapi/asm-arm64/asm/kvm.h
@@ -147,6 +147,9 @@
 #define KVM_ARM_VCPU_PMU_V3_CTRL 0
 #define KVM_ARM_VCPU_PMU_V3_IRQ 0
 #define KVM_ARM_VCPU_PMU_V3_INIT 1
+#define KVM_ARM_VCPU_TIMER_CTRL 1
+#define KVM_ARM_VCPU_TIMER_IRQ_VTIMER 0
+#define KVM_ARM_VCPU_TIMER_IRQ_PTIMER 1
 #define KVM_ARM_IRQ_TYPE_SHIFT 24
 #define KVM_ARM_IRQ_TYPE_MASK 0xff
 #define KVM_ARM_IRQ_VCPU_SHIFT 16
diff --git a/libc/kernel/uapi/asm-arm64/asm/sigcontext.h b/libc/kernel/uapi/asm-arm64/asm/sigcontext.h
index 80d61b0..be2464e 100644
--- a/libc/kernel/uapi/asm-arm64/asm/sigcontext.h
+++ b/libc/kernel/uapi/asm-arm64/asm/sigcontext.h
@@ -43,4 +43,11 @@
   struct _aarch64_ctx head;
   __u64 esr;
 };
+#define EXTRA_MAGIC 0x45585401
+struct extra_context {
+  struct _aarch64_ctx head;
+  __u64 datap;
+  __u32 size;
+  __u32 __reserved[3];
+};
 #endif
diff --git a/libc/kernel/uapi/asm-generic/hugetlb_encode.h b/libc/kernel/uapi/asm-generic/hugetlb_encode.h
new file mode 100644
index 0000000..68849b3
--- /dev/null
+++ b/libc/kernel/uapi/asm-generic/hugetlb_encode.h
@@ -0,0 +1,33 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ***   To edit the content of this header, modify the corresponding
+ ***   source file (e.g. under external/kernel-headers/original/) then
+ ***   run bionic/libc/kernel/tools/update_all.py
+ ***
+ ***   Any manual change here will be lost the next time this script will
+ ***   be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _ASM_GENERIC_HUGETLB_ENCODE_H_
+#define _ASM_GENERIC_HUGETLB_ENCODE_H_
+#define HUGETLB_FLAG_ENCODE_SHIFT 26
+#define HUGETLB_FLAG_ENCODE_MASK 0x3f
+#define HUGETLB_FLAG_ENCODE_64KB (16 << HUGETLB_FLAG_ENCODE_SHIFT)
+#define HUGETLB_FLAG_ENCODE_512KB (19 << HUGETLB_FLAG_ENCODE_SHIFT)
+#define HUGETLB_FLAG_ENCODE_1MB (20 << HUGETLB_FLAG_ENCODE_SHIFT)
+#define HUGETLB_FLAG_ENCODE_2MB (21 << HUGETLB_FLAG_ENCODE_SHIFT)
+#define HUGETLB_FLAG_ENCODE_8MB (23 << HUGETLB_FLAG_ENCODE_SHIFT)
+#define HUGETLB_FLAG_ENCODE_16MB (24 << HUGETLB_FLAG_ENCODE_SHIFT)
+#define HUGETLB_FLAG_ENCODE_256MB (28 << HUGETLB_FLAG_ENCODE_SHIFT)
+#define HUGETLB_FLAG_ENCODE_1GB (30 << HUGETLB_FLAG_ENCODE_SHIFT)
+#define HUGETLB_FLAG_ENCODE_2GB (31 << HUGETLB_FLAG_ENCODE_SHIFT)
+#define HUGETLB_FLAG_ENCODE_16GB (34 << HUGETLB_FLAG_ENCODE_SHIFT)
+#endif
diff --git a/libc/kernel/uapi/asm-generic/ioctls.h b/libc/kernel/uapi/asm-generic/ioctls.h
index 792bf0f..41dbce2 100644
--- a/libc/kernel/uapi/asm-generic/ioctls.h
+++ b/libc/kernel/uapi/asm-generic/ioctls.h
@@ -80,6 +80,7 @@
 #define TIOCGPKT _IOR('T', 0x38, int)
 #define TIOCGPTLCK _IOR('T', 0x39, int)
 #define TIOCGEXCL _IOR('T', 0x40, int)
+#define TIOCGPTPEER _IO('T', 0x41)
 #define FIONCLEX 0x5450
 #define FIOCLEX 0x5451
 #define FIOASYNC 0x5452
diff --git a/libc/kernel/uapi/asm-generic/mman-common.h b/libc/kernel/uapi/asm-generic/mman-common.h
index 047743d..a15624a 100644
--- a/libc/kernel/uapi/asm-generic/mman-common.h
+++ b/libc/kernel/uapi/asm-generic/mman-common.h
@@ -52,9 +52,9 @@
 #define MADV_NOHUGEPAGE 15
 #define MADV_DONTDUMP 16
 #define MADV_DODUMP 17
+#define MADV_WIPEONFORK 18
+#define MADV_KEEPONFORK 19
 #define MAP_FILE 0
-#define MAP_HUGE_SHIFT 26
-#define MAP_HUGE_MASK 0x3f
 #define PKEY_DISABLE_ACCESS 0x1
 #define PKEY_DISABLE_WRITE 0x2
 #define PKEY_ACCESS_MASK (PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE)
diff --git a/libc/kernel/uapi/asm-generic/siginfo.h b/libc/kernel/uapi/asm-generic/siginfo.h
index f98fd73..669c9d4 100644
--- a/libc/kernel/uapi/asm-generic/siginfo.h
+++ b/libc/kernel/uapi/asm-generic/siginfo.h
@@ -126,75 +126,66 @@
 #define si_syscall _sifields._sigsys._syscall
 #define si_arch _sifields._sigsys._arch
 #endif
-#define __SI_KILL 0
-#define __SI_TIMER 0
-#define __SI_POLL 0
-#define __SI_FAULT 0
-#define __SI_CHLD 0
-#define __SI_RT 0
-#define __SI_MESGQ 0
-#define __SI_SYS 0
-#define __SI_CODE(T,N) (N)
 #define SI_USER 0
 #define SI_KERNEL 0x80
 #define SI_QUEUE - 1
-#define SI_TIMER __SI_CODE(__SI_TIMER, - 2)
-#define SI_MESGQ __SI_CODE(__SI_MESGQ, - 3)
+#define SI_TIMER - 2
+#define SI_MESGQ - 3
 #define SI_ASYNCIO - 4
 #define SI_SIGIO - 5
 #define SI_TKILL - 6
 #define SI_DETHREAD - 7
 #define SI_FROMUSER(siptr) ((siptr)->si_code <= 0)
 #define SI_FROMKERNEL(siptr) ((siptr)->si_code > 0)
-#define ILL_ILLOPC (__SI_FAULT | 1)
-#define ILL_ILLOPN (__SI_FAULT | 2)
-#define ILL_ILLADR (__SI_FAULT | 3)
-#define ILL_ILLTRP (__SI_FAULT | 4)
-#define ILL_PRVOPC (__SI_FAULT | 5)
-#define ILL_PRVREG (__SI_FAULT | 6)
-#define ILL_COPROC (__SI_FAULT | 7)
-#define ILL_BADSTK (__SI_FAULT | 8)
+#define ILL_ILLOPC 1
+#define ILL_ILLOPN 2
+#define ILL_ILLADR 3
+#define ILL_ILLTRP 4
+#define ILL_PRVOPC 5
+#define ILL_PRVREG 6
+#define ILL_COPROC 7
+#define ILL_BADSTK 8
 #define NSIGILL 8
-#define FPE_INTDIV (__SI_FAULT | 1)
-#define FPE_INTOVF (__SI_FAULT | 2)
-#define FPE_FLTDIV (__SI_FAULT | 3)
-#define FPE_FLTOVF (__SI_FAULT | 4)
-#define FPE_FLTUND (__SI_FAULT | 5)
-#define FPE_FLTRES (__SI_FAULT | 6)
-#define FPE_FLTINV (__SI_FAULT | 7)
-#define FPE_FLTSUB (__SI_FAULT | 8)
+#define FPE_INTDIV 1
+#define FPE_INTOVF 2
+#define FPE_FLTDIV 3
+#define FPE_FLTOVF 4
+#define FPE_FLTUND 5
+#define FPE_FLTRES 6
+#define FPE_FLTINV 7
+#define FPE_FLTSUB 8
 #define NSIGFPE 8
-#define SEGV_MAPERR (__SI_FAULT | 1)
-#define SEGV_ACCERR (__SI_FAULT | 2)
-#define SEGV_BNDERR (__SI_FAULT | 3)
-#define SEGV_PKUERR (__SI_FAULT | 4)
+#define SEGV_MAPERR 1
+#define SEGV_ACCERR 2
+#define SEGV_BNDERR 3
+#define SEGV_PKUERR 4
 #define NSIGSEGV 4
-#define BUS_ADRALN (__SI_FAULT | 1)
-#define BUS_ADRERR (__SI_FAULT | 2)
-#define BUS_OBJERR (__SI_FAULT | 3)
-#define BUS_MCEERR_AR (__SI_FAULT | 4)
-#define BUS_MCEERR_AO (__SI_FAULT | 5)
+#define BUS_ADRALN 1
+#define BUS_ADRERR 2
+#define BUS_OBJERR 3
+#define BUS_MCEERR_AR 4
+#define BUS_MCEERR_AO 5
 #define NSIGBUS 5
-#define TRAP_BRKPT (__SI_FAULT | 1)
-#define TRAP_TRACE (__SI_FAULT | 2)
-#define TRAP_BRANCH (__SI_FAULT | 3)
-#define TRAP_HWBKPT (__SI_FAULT | 4)
+#define TRAP_BRKPT 1
+#define TRAP_TRACE 2
+#define TRAP_BRANCH 3
+#define TRAP_HWBKPT 4
 #define NSIGTRAP 4
-#define CLD_EXITED (__SI_CHLD | 1)
-#define CLD_KILLED (__SI_CHLD | 2)
-#define CLD_DUMPED (__SI_CHLD | 3)
-#define CLD_TRAPPED (__SI_CHLD | 4)
-#define CLD_STOPPED (__SI_CHLD | 5)
-#define CLD_CONTINUED (__SI_CHLD | 6)
+#define CLD_EXITED 1
+#define CLD_KILLED 2
+#define CLD_DUMPED 3
+#define CLD_TRAPPED 4
+#define CLD_STOPPED 5
+#define CLD_CONTINUED 6
 #define NSIGCHLD 6
-#define POLL_IN (__SI_POLL | 1)
-#define POLL_OUT (__SI_POLL | 2)
-#define POLL_MSG (__SI_POLL | 3)
-#define POLL_ERR (__SI_POLL | 4)
-#define POLL_PRI (__SI_POLL | 5)
-#define POLL_HUP (__SI_POLL | 6)
+#define POLL_IN 1
+#define POLL_OUT 2
+#define POLL_MSG 3
+#define POLL_ERR 4
+#define POLL_PRI 5
+#define POLL_HUP 6
 #define NSIGPOLL 6
-#define SYS_SECCOMP (__SI_SYS | 1)
+#define SYS_SECCOMP 1
 #define NSIGSYS 1
 #define SIGEV_SIGNAL 0
 #define SIGEV_NONE 1
diff --git a/libc/kernel/uapi/asm-generic/socket.h b/libc/kernel/uapi/asm-generic/socket.h
index d1dc0099..b821554 100644
--- a/libc/kernel/uapi/asm-generic/socket.h
+++ b/libc/kernel/uapi/asm-generic/socket.h
@@ -85,4 +85,7 @@
 #define SO_MEMINFO 55
 #define SO_INCOMING_NAPI_ID 56
 #define SO_COOKIE 57
+#define SCM_TIMESTAMPING_PKTINFO 58
+#define SO_PEERGROUPS 59
+#define SO_ZEROCOPY 60
 #endif
diff --git a/libc/kernel/uapi/asm-mips/asm/inst.h b/libc/kernel/uapi/asm-mips/asm/inst.h
index 46a65e6..61fa3d6 100644
--- a/libc/kernel/uapi/asm-mips/asm/inst.h
+++ b/libc/kernel/uapi/asm-mips/asm/inst.h
@@ -414,10 +414,13 @@
 };
 enum bshfl_func {
   wsbh_op = 0x2,
-  dshd_op = 0x5,
   seb_op = 0x10,
   seh_op = 0x18,
 };
+enum dbshfl_func {
+  dsbh_op = 0x2,
+  dshd_op = 0x5,
+};
 enum msa_func {
   msa_elm_op = 0x19,
 };
@@ -798,6 +801,10 @@
   __BITFIELD_FIELD(unsigned int opcode : 6, __BITFIELD_FIELD(signed int s10 : 10, __BITFIELD_FIELD(unsigned int rs : 5, __BITFIELD_FIELD(unsigned int wd : 5, __BITFIELD_FIELD(unsigned int func : 4, __BITFIELD_FIELD(unsigned int df : 2,;
  ))))))
 };
+struct dsp_format {
+  __BITFIELD_FIELD(unsigned int opcode : 6, __BITFIELD_FIELD(unsigned int base : 5, __BITFIELD_FIELD(unsigned int index : 5, __BITFIELD_FIELD(unsigned int rd : 5, __BITFIELD_FIELD(unsigned int op : 5, __BITFIELD_FIELD(unsigned int func : 6,;
+ ))))))
+};
 struct spec3_format {
   __BITFIELD_FIELD(unsigned int opcode : 6, __BITFIELD_FIELD(unsigned int rs : 5, __BITFIELD_FIELD(unsigned int rt : 5, __BITFIELD_FIELD(signed int simmediate : 9, __BITFIELD_FIELD(unsigned int func : 7,;
  )))))
@@ -883,7 +890,7 @@
  ))))
 };
 struct mm16_r5_format {
-  __BITFIELD_FIELD(unsigned int opcode : 6, __BITFIELD_FIELD(unsigned int rt : 5, __BITFIELD_FIELD(signed int simmediate : 5, __BITFIELD_FIELD(unsigned int : 16,;
+  __BITFIELD_FIELD(unsigned int opcode : 6, __BITFIELD_FIELD(unsigned int rt : 5, __BITFIELD_FIELD(unsigned int imm : 5, __BITFIELD_FIELD(unsigned int : 16,;
  ))))
 };
 struct m16e_rr {
@@ -933,6 +940,7 @@
   struct b_format b_format;
   struct ps_format ps_format;
   struct v_format v_format;
+  struct dsp_format dsp_format;
   struct spec3_format spec3_format;
   struct fb_format fb_format;
   struct fp0_format fp0_format;
diff --git a/libc/kernel/uapi/asm-mips/asm/ioctls.h b/libc/kernel/uapi/asm-mips/asm/ioctls.h
index 1845c65..a4a40b0 100644
--- a/libc/kernel/uapi/asm-mips/asm/ioctls.h
+++ b/libc/kernel/uapi/asm-mips/asm/ioctls.h
@@ -84,6 +84,7 @@
 #define TIOCGPKT _IOR('T', 0x38, int)
 #define TIOCGPTLCK _IOR('T', 0x39, int)
 #define TIOCGEXCL _IOR('T', 0x40, int)
+#define TIOCGPTPEER _IO('T', 0x41)
 #define TIOCSCTTY 0x5480
 #define TIOCGSOFTCAR 0x5481
 #define TIOCSSOFTCAR 0x5482
diff --git a/libc/kernel/uapi/asm-mips/asm/mman.h b/libc/kernel/uapi/asm-mips/asm/mman.h
index ad08f7a..b976885 100644
--- a/libc/kernel/uapi/asm-mips/asm/mman.h
+++ b/libc/kernel/uapi/asm-mips/asm/mman.h
@@ -66,9 +66,9 @@
 #define MADV_NOHUGEPAGE 15
 #define MADV_DONTDUMP 16
 #define MADV_DODUMP 17
+#define MADV_WIPEONFORK 18
+#define MADV_KEEPONFORK 19
 #define MAP_FILE 0
-#define MAP_HUGE_SHIFT 26
-#define MAP_HUGE_MASK 0x3f
 #define PKEY_DISABLE_ACCESS 0x1
 #define PKEY_DISABLE_WRITE 0x2
 #define PKEY_ACCESS_MASK (PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE)
diff --git a/libc/kernel/uapi/asm-mips/asm/siginfo.h b/libc/kernel/uapi/asm-mips/asm/siginfo.h
index b652925..413abd9 100644
--- a/libc/kernel/uapi/asm-mips/asm/siginfo.h
+++ b/libc/kernel/uapi/asm-mips/asm/siginfo.h
@@ -95,6 +95,6 @@
 #undef SI_TIMER
 #undef SI_MESGQ
 #define SI_ASYNCIO - 2
-#define SI_TIMER __SI_CODE(__SI_TIMER, - 3)
-#define SI_MESGQ __SI_CODE(__SI_MESGQ, - 4)
+#define SI_TIMER - 3
+#define SI_MESGQ - 4
 #endif
diff --git a/libc/kernel/uapi/asm-mips/asm/socket.h b/libc/kernel/uapi/asm-mips/asm/socket.h
index e97ae58..b8de15c 100644
--- a/libc/kernel/uapi/asm-mips/asm/socket.h
+++ b/libc/kernel/uapi/asm-mips/asm/socket.h
@@ -84,4 +84,7 @@
 #define SO_MEMINFO 55
 #define SO_INCOMING_NAPI_ID 56
 #define SO_COOKIE 57
+#define SCM_TIMESTAMPING_PKTINFO 58
+#define SO_PEERGROUPS 59
+#define SO_ZEROCOPY 60
 #endif
diff --git a/libc/kernel/uapi/asm-x86/asm/hyperv.h b/libc/kernel/uapi/asm-x86/asm/hyperv.h
index 2d4b97a..d5c9b19 100644
--- a/libc/kernel/uapi/asm-x86/asm/hyperv.h
+++ b/libc/kernel/uapi/asm-x86/asm/hyperv.h
@@ -32,8 +32,7 @@
 #define HV_X64_MSR_TIME_REF_COUNT_AVAILABLE (1 << 1)
 #define HV_X64_MSR_REFERENCE_TSC_AVAILABLE (1 << 9)
 #define HV_X64_MSR_REFERENCE_TSC 0x40000021
-#define HV_X64_MSR_APIC_FREQUENCY_AVAILABLE (1 << 11)
-#define HV_X64_MSR_TSC_FREQUENCY_AVAILABLE (1 << 11)
+#define HV_X64_ACCESS_FREQUENCY_MSRS (1 << 11)
 #define HV_X64_MSR_SYNIC_AVAILABLE (1 << 2)
 #define HV_X64_MSR_SYNTIMER_AVAILABLE (1 << 3)
 #define HV_X64_MSR_APIC_ACCESS_AVAILABLE (1 << 4)
@@ -41,6 +40,7 @@
 #define HV_X64_MSR_VP_INDEX_AVAILABLE (1 << 6)
 #define HV_X64_MSR_RESET_AVAILABLE (1 << 7)
 #define HV_X64_MSR_STAT_PAGES_AVAILABLE (1 << 8)
+#define HV_FEATURE_FREQUENCY_MSRS_AVAILABLE (1 << 8)
 #define HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE (1 << 10)
 #define HV_X64_CREATE_PARTITIONS (1 << 0)
 #define HV_X64_ACCESS_PARTITION_ID (1 << 1)
@@ -68,6 +68,7 @@
 #define HV_X64_SYSTEM_RESET_RECOMMENDED (1 << 4)
 #define HV_X64_RELAXED_TIMING_RECOMMENDED (1 << 5)
 #define HV_X64_DEPRECATING_AEOI_RECOMMENDED (1 << 9)
+#define HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED (1 << 11)
 #define HV_CRASH_CTL_CRASH_NOTIFY (1ULL << 63)
 #define HV_X64_MSR_GUEST_OS_ID 0x40000000
 #define HV_X64_MSR_HYPERCALL 0x40000001
@@ -121,7 +122,11 @@
 #define HV_X64_MSR_HYPERCALL_ENABLE 0x00000001
 #define HV_X64_MSR_HYPERCALL_PAGE_ADDRESS_SHIFT 12
 #define HV_X64_MSR_HYPERCALL_PAGE_ADDRESS_MASK (~((1ull << HV_X64_MSR_HYPERCALL_PAGE_ADDRESS_SHIFT) - 1))
+#define HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE 0x0002
+#define HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST 0x0003
 #define HVCALL_NOTIFY_LONG_SPIN_WAIT 0x0008
+#define HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE_EX 0x0013
+#define HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST_EX 0x0014
 #define HVCALL_POST_MESSAGE 0x005c
 #define HVCALL_SIGNAL_EVENT 0x005d
 #define HV_X64_MSR_APIC_ASSIST_PAGE_ENABLE 0x00000001
@@ -133,6 +138,14 @@
 #define HV_PROCESSOR_POWER_STATE_C1 1
 #define HV_PROCESSOR_POWER_STATE_C2 2
 #define HV_PROCESSOR_POWER_STATE_C3 3
+#define HV_FLUSH_ALL_PROCESSORS BIT(0)
+#define HV_FLUSH_ALL_VIRTUAL_ADDRESS_SPACES BIT(1)
+#define HV_FLUSH_NON_GLOBAL_MAPPINGS_ONLY BIT(2)
+#define HV_FLUSH_USE_EXTENDED_RANGE_FORMAT BIT(3)
+enum HV_GENERIC_SET_FORMAT {
+  HV_GENERIC_SET_SPARCE_4K,
+  HV_GENERIC_SET_ALL,
+};
 #define HV_STATUS_SUCCESS 0
 #define HV_STATUS_INVALID_HYPERCALL_CODE 2
 #define HV_STATUS_INVALID_HYPERCALL_INPUT 3
diff --git a/libc/kernel/uapi/asm-x86/asm/kvm_para.h b/libc/kernel/uapi/asm-x86/asm/kvm_para.h
index 78008df..b7635cb 100644
--- a/libc/kernel/uapi/asm-x86/asm/kvm_para.h
+++ b/libc/kernel/uapi/asm-x86/asm/kvm_para.h
@@ -61,6 +61,7 @@
 #define KVM_MAX_MMU_OP_BATCH 32
 #define KVM_ASYNC_PF_ENABLED (1 << 0)
 #define KVM_ASYNC_PF_SEND_ALWAYS (1 << 1)
+#define KVM_ASYNC_PF_DELIVERY_AS_PF_VMEXIT (1 << 2)
 #define KVM_MMU_OP_WRITE_PTE 1
 #define KVM_MMU_OP_FLUSH_TLB 2
 #define KVM_MMU_OP_RELEASE_PT 3
diff --git a/libc/kernel/uapi/asm-x86/asm/mman.h b/libc/kernel/uapi/asm-x86/asm/mman.h
index b958829..1061a6f 100644
--- a/libc/kernel/uapi/asm-x86/asm/mman.h
+++ b/libc/kernel/uapi/asm-x86/asm/mman.h
@@ -19,7 +19,5 @@
 #ifndef _ASM_X86_MMAN_H
 #define _ASM_X86_MMAN_H
 #define MAP_32BIT 0x40
-#define MAP_HUGE_2MB (21 << MAP_HUGE_SHIFT)
-#define MAP_HUGE_1GB (30 << MAP_HUGE_SHIFT)
 #include <asm-generic/mman.h>
 #endif
diff --git a/libc/kernel/uapi/asm-x86/asm/processor-flags.h b/libc/kernel/uapi/asm-x86/asm/processor-flags.h
index 9f61c0a..f0f8dd2 100644
--- a/libc/kernel/uapi/asm-x86/asm/processor-flags.h
+++ b/libc/kernel/uapi/asm-x86/asm/processor-flags.h
@@ -104,6 +104,8 @@
 #define X86_CR4_OSFXSR _BITUL(X86_CR4_OSFXSR_BIT)
 #define X86_CR4_OSXMMEXCPT_BIT 10
 #define X86_CR4_OSXMMEXCPT _BITUL(X86_CR4_OSXMMEXCPT_BIT)
+#define X86_CR4_LA57_BIT 12
+#define X86_CR4_LA57 _BITUL(X86_CR4_LA57_BIT)
 #define X86_CR4_VMXE_BIT 13
 #define X86_CR4_VMXE _BITUL(X86_CR4_VMXE_BIT)
 #define X86_CR4_SMXE_BIT 14
diff --git a/libc/kernel/uapi/drm/amdgpu_drm.h b/libc/kernel/uapi/drm/amdgpu_drm.h
index f5e8b16..6ae9c9c 100644
--- a/libc/kernel/uapi/drm/amdgpu_drm.h
+++ b/libc/kernel/uapi/drm/amdgpu_drm.h
@@ -34,6 +34,7 @@
 #define DRM_AMDGPU_GEM_OP 0x10
 #define DRM_AMDGPU_GEM_USERPTR 0x11
 #define DRM_AMDGPU_WAIT_FENCES 0x12
+#define DRM_AMDGPU_VM 0x13
 #define DRM_IOCTL_AMDGPU_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_CREATE, union drm_amdgpu_gem_create)
 #define DRM_IOCTL_AMDGPU_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_MMAP, union drm_amdgpu_gem_mmap)
 #define DRM_IOCTL_AMDGPU_CTX DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_CTX, union drm_amdgpu_ctx)
@@ -47,6 +48,7 @@
 #define DRM_IOCTL_AMDGPU_GEM_OP DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_OP, struct drm_amdgpu_gem_op)
 #define DRM_IOCTL_AMDGPU_GEM_USERPTR DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_USERPTR, struct drm_amdgpu_gem_userptr)
 #define DRM_IOCTL_AMDGPU_WAIT_FENCES DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_WAIT_FENCES, union drm_amdgpu_wait_fences)
+#define DRM_IOCTL_AMDGPU_VM DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_VM, union drm_amdgpu_vm)
 #define AMDGPU_GEM_DOMAIN_CPU 0x1
 #define AMDGPU_GEM_DOMAIN_GTT 0x2
 #define AMDGPU_GEM_DOMAIN_VRAM 0x4
@@ -123,6 +125,19 @@
   struct drm_amdgpu_ctx_in in;
   union drm_amdgpu_ctx_out out;
 };
+#define AMDGPU_VM_OP_RESERVE_VMID 1
+#define AMDGPU_VM_OP_UNRESERVE_VMID 2
+struct drm_amdgpu_vm_in {
+  __u32 op;
+  __u32 flags;
+};
+struct drm_amdgpu_vm_out {
+  __u64 flags;
+};
+union drm_amdgpu_vm {
+  struct drm_amdgpu_vm_in in;
+  struct drm_amdgpu_vm_out out;
+};
 #define AMDGPU_GEM_USERPTR_READONLY (1 << 0)
 #define AMDGPU_GEM_USERPTR_ANONONLY (1 << 1)
 #define AMDGPU_GEM_USERPTR_VALIDATE (1 << 2)
@@ -262,11 +277,15 @@
 #define AMDGPU_HW_IP_UVD 3
 #define AMDGPU_HW_IP_VCE 4
 #define AMDGPU_HW_IP_UVD_ENC 5
-#define AMDGPU_HW_IP_NUM 6
+#define AMDGPU_HW_IP_VCN_DEC 6
+#define AMDGPU_HW_IP_VCN_ENC 7
+#define AMDGPU_HW_IP_NUM 8
 #define AMDGPU_HW_IP_INSTANCE_MAX_COUNT 1
 #define AMDGPU_CHUNK_ID_IB 0x01
 #define AMDGPU_CHUNK_ID_FENCE 0x02
 #define AMDGPU_CHUNK_ID_DEPENDENCIES 0x03
+#define AMDGPU_CHUNK_ID_SYNCOBJ_IN 0x04
+#define AMDGPU_CHUNK_ID_SYNCOBJ_OUT 0x05
 struct drm_amdgpu_cs_chunk {
   __u32 chunk_id;
   __u32 length_dw;
@@ -309,6 +328,9 @@
   __u32 handle;
   __u32 offset;
 };
+struct drm_amdgpu_cs_chunk_sem {
+  __u32 handle;
+};
 struct drm_amdgpu_cs_chunk_data {
   union {
     struct drm_amdgpu_cs_chunk_ib ib_data;
@@ -358,6 +380,7 @@
 #define AMDGPU_INFO_SENSOR_GPU_AVG_POWER 0x5
 #define AMDGPU_INFO_SENSOR_VDDNB 0x6
 #define AMDGPU_INFO_SENSOR_VDDGFX 0x7
+#define AMDGPU_INFO_NUM_VRAM_CPU_PAGE_FAULTS 0x1E
 #define AMDGPU_INFO_MMR_SE_INDEX_SHIFT 0
 #define AMDGPU_INFO_MMR_SE_INDEX_MASK 0xff
 #define AMDGPU_INFO_MMR_SH_INDEX_SHIFT 8
@@ -480,6 +503,7 @@
   __u32 gs_prim_buffer_depth;
   __u32 max_gs_waves_per_vgt;
   __u32 _pad1;
+  __u32 cu_ao_bitmap[4][4];
 };
 struct drm_amdgpu_info_hw_ip {
   __u32 hw_ip_version_major;
@@ -513,6 +537,7 @@
 #define AMDGPU_FAMILY_VI 130
 #define AMDGPU_FAMILY_CZ 135
 #define AMDGPU_FAMILY_AI 141
+#define AMDGPU_FAMILY_RV 142
 #ifdef __cplusplus
 #endif
 #endif
diff --git a/libc/kernel/uapi/drm/armada_drm.h b/libc/kernel/uapi/drm/armada_drm.h
index 331a558..ea1f37d 100644
--- a/libc/kernel/uapi/drm/armada_drm.h
+++ b/libc/kernel/uapi/drm/armada_drm.h
@@ -26,23 +26,23 @@
 #define DRM_ARMADA_GEM_PWRITE 0x03
 #define ARMADA_IOCTL(dir,name,str) DRM_ ##dir(DRM_COMMAND_BASE + DRM_ARMADA_ ##name, struct drm_armada_ ##str)
 struct drm_armada_gem_create {
-  uint32_t handle;
-  uint32_t size;
+  __u32 handle;
+  __u32 size;
 };
 #define DRM_IOCTL_ARMADA_GEM_CREATE ARMADA_IOCTL(IOWR, GEM_CREATE, gem_create)
 struct drm_armada_gem_mmap {
-  uint32_t handle;
-  uint32_t pad;
-  uint64_t offset;
-  uint64_t size;
-  uint64_t addr;
+  __u32 handle;
+  __u32 pad;
+  __u64 offset;
+  __u64 size;
+  __u64 addr;
 };
 #define DRM_IOCTL_ARMADA_GEM_MMAP ARMADA_IOCTL(IOWR, GEM_MMAP, gem_mmap)
 struct drm_armada_gem_pwrite {
-  uint64_t ptr;
-  uint32_t handle;
-  uint32_t offset;
-  uint32_t size;
+  __u64 ptr;
+  __u32 handle;
+  __u32 offset;
+  __u32 size;
 };
 #define DRM_IOCTL_ARMADA_GEM_PWRITE ARMADA_IOCTL(IOW, GEM_PWRITE, gem_pwrite)
 #ifdef __cplusplus
diff --git a/libc/kernel/uapi/drm/drm.h b/libc/kernel/uapi/drm/drm.h
index 251deeb..6863dc1 100644
--- a/libc/kernel/uapi/drm/drm.h
+++ b/libc/kernel/uapi/drm/drm.h
@@ -361,6 +361,7 @@
 #define DRM_CAP_ADDFB2_MODIFIERS 0x10
 #define DRM_CAP_PAGE_FLIP_TARGET 0x11
 #define DRM_CAP_CRTC_IN_VBLANK_EVENT 0x12
+#define DRM_CAP_SYNCOBJ 0x13
 struct drm_get_cap {
   __u64 capability;
   __u64 value;
@@ -379,6 +380,38 @@
   __u32 flags;
   __s32 fd;
 };
+struct drm_syncobj_create {
+  __u32 handle;
+#define DRM_SYNCOBJ_CREATE_SIGNALED (1 << 0)
+  __u32 flags;
+};
+struct drm_syncobj_destroy {
+  __u32 handle;
+  __u32 pad;
+};
+#define DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE (1 << 0)
+#define DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE (1 << 0)
+struct drm_syncobj_handle {
+  __u32 handle;
+  __u32 flags;
+  __s32 fd;
+  __u32 pad;
+};
+#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL (1 << 0)
+#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT (1 << 1)
+struct drm_syncobj_wait {
+  __u64 handles;
+  __s64 timeout_nsec;
+  __u32 count_handles;
+  __u32 flags;
+  __u32 first_signaled;
+  __u32 pad;
+};
+struct drm_syncobj_array {
+  __u64 handles;
+  __u32 count_handles;
+  __u32 pad;
+};
 #ifdef __cplusplus
 #endif
 #include "drm_mode.h"
@@ -477,6 +510,13 @@
 #define DRM_IOCTL_MODE_ATOMIC DRM_IOWR(0xBC, struct drm_mode_atomic)
 #define DRM_IOCTL_MODE_CREATEPROPBLOB DRM_IOWR(0xBD, struct drm_mode_create_blob)
 #define DRM_IOCTL_MODE_DESTROYPROPBLOB DRM_IOWR(0xBE, struct drm_mode_destroy_blob)
+#define DRM_IOCTL_SYNCOBJ_CREATE DRM_IOWR(0xBF, struct drm_syncobj_create)
+#define DRM_IOCTL_SYNCOBJ_DESTROY DRM_IOWR(0xC0, struct drm_syncobj_destroy)
+#define DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD DRM_IOWR(0xC1, struct drm_syncobj_handle)
+#define DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE DRM_IOWR(0xC2, struct drm_syncobj_handle)
+#define DRM_IOCTL_SYNCOBJ_WAIT DRM_IOWR(0xC3, struct drm_syncobj_wait)
+#define DRM_IOCTL_SYNCOBJ_RESET DRM_IOWR(0xC4, struct drm_syncobj_array)
+#define DRM_IOCTL_SYNCOBJ_SIGNAL DRM_IOWR(0xC5, struct drm_syncobj_array)
 #define DRM_COMMAND_BASE 0x40
 #define DRM_COMMAND_END 0xA0
 struct drm_event {
diff --git a/libc/kernel/uapi/drm/drm_fourcc.h b/libc/kernel/uapi/drm/drm_fourcc.h
index 630ad30..da416cf 100644
--- a/libc/kernel/uapi/drm/drm_fourcc.h
+++ b/libc/kernel/uapi/drm/drm_fourcc.h
@@ -105,11 +105,16 @@
 #define DRM_FORMAT_MOD_VENDOR_SAMSUNG 0x04
 #define DRM_FORMAT_MOD_VENDOR_QCOM 0x05
 #define DRM_FORMAT_MOD_VENDOR_VIVANTE 0x06
+#define DRM_FORMAT_MOD_VENDOR_BROADCOM 0x07
+#define DRM_FORMAT_RESERVED ((1ULL << 56) - 1)
 #define fourcc_mod_code(vendor,val) ((((__u64) DRM_FORMAT_MOD_VENDOR_ ##vendor) << 56) | (val & 0x00ffffffffffffffULL))
+#define DRM_FORMAT_MOD_INVALID fourcc_mod_code(NONE, DRM_FORMAT_RESERVED)
 #define DRM_FORMAT_MOD_LINEAR fourcc_mod_code(NONE, 0)
 #define I915_FORMAT_MOD_X_TILED fourcc_mod_code(INTEL, 1)
 #define I915_FORMAT_MOD_Y_TILED fourcc_mod_code(INTEL, 2)
 #define I915_FORMAT_MOD_Yf_TILED fourcc_mod_code(INTEL, 3)
+#define I915_FORMAT_MOD_Y_TILED_CCS fourcc_mod_code(INTEL, 4)
+#define I915_FORMAT_MOD_Yf_TILED_CCS fourcc_mod_code(INTEL, 5)
 #define DRM_FORMAT_MOD_SAMSUNG_64_32_TILE fourcc_mod_code(SAMSUNG, 1)
 #define DRM_FORMAT_MOD_VIVANTE_TILED fourcc_mod_code(VIVANTE, 1)
 #define DRM_FORMAT_MOD_VIVANTE_SUPER_TILED fourcc_mod_code(VIVANTE, 2)
@@ -121,6 +126,7 @@
 #define fourcc_mod_tegra_param(m) (m & ((1ULL << __fourcc_mod_tegra_mode_shift) - 1))
 #define NV_FORMAT_MOD_TEGRA_TILED fourcc_mod_tegra_code(1, 0)
 #define NV_FORMAT_MOD_TEGRA_16BX2_BLOCK(v) fourcc_mod_tegra_code(2, v)
+#define DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED fourcc_mod_code(BROADCOM, 1)
 #ifdef __cplusplus
 #endif
 #endif
diff --git a/libc/kernel/uapi/drm/drm_mode.h b/libc/kernel/uapi/drm/drm_mode.h
index 9e7ee92..5e97a72 100644
--- a/libc/kernel/uapi/drm/drm_mode.h
+++ b/libc/kernel/uapi/drm/drm_mode.h
@@ -79,6 +79,14 @@
 #define DRM_MODE_DIRTY_ANNOTATE 2
 #define DRM_MODE_LINK_STATUS_GOOD 0
 #define DRM_MODE_LINK_STATUS_BAD 1
+#define DRM_MODE_ROTATE_0 (1 << 0)
+#define DRM_MODE_ROTATE_90 (1 << 1)
+#define DRM_MODE_ROTATE_180 (1 << 2)
+#define DRM_MODE_ROTATE_270 (1 << 3)
+#define DRM_MODE_ROTATE_MASK (DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270)
+#define DRM_MODE_REFLECT_X (1 << 4)
+#define DRM_MODE_REFLECT_Y (1 << 5)
+#define DRM_MODE_REFLECT_MASK (DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y)
 struct drm_mode_modeinfo {
   __u32 clock;
   __u16 hdisplay;
@@ -396,6 +404,21 @@
   __u64 reserved;
   __u64 user_data;
 };
+struct drm_format_modifier_blob {
+#define FORMAT_BLOB_CURRENT 1
+  __u32 version;
+  __u32 flags;
+  __u32 count_formats;
+  __u32 formats_offset;
+  __u32 count_modifiers;
+  __u32 modifiers_offset;
+};
+struct drm_format_modifier {
+  __u64 formats;
+  __u32 offset;
+  __u32 pad;
+  __u64 modifier;
+};
 struct drm_mode_create_blob {
   __u64 data;
   __u32 length;
diff --git a/libc/kernel/uapi/drm/i915_drm.h b/libc/kernel/uapi/drm/i915_drm.h
index af6f064..50ea43a 100644
--- a/libc/kernel/uapi/drm/i915_drm.h
+++ b/libc/kernel/uapi/drm/i915_drm.h
@@ -172,6 +172,8 @@
 #define DRM_I915_GEM_CONTEXT_GETPARAM 0x34
 #define DRM_I915_GEM_CONTEXT_SETPARAM 0x35
 #define DRM_I915_PERF_OPEN 0x36
+#define DRM_I915_PERF_ADD_CONFIG 0x37
+#define DRM_I915_PERF_REMOVE_CONFIG 0x38
 #define DRM_IOCTL_I915_INIT DRM_IOW(DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
 #define DRM_IOCTL_I915_FLUSH DRM_IO(DRM_COMMAND_BASE + DRM_I915_FLUSH)
 #define DRM_IOCTL_I915_FLIP DRM_IO(DRM_COMMAND_BASE + DRM_I915_FLIP)
@@ -226,6 +228,8 @@
 #define DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_GETPARAM, struct drm_i915_gem_context_param)
 #define DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_SETPARAM, struct drm_i915_gem_context_param)
 #define DRM_IOCTL_I915_PERF_OPEN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_OPEN, struct drm_i915_perf_open_param)
+#define DRM_IOCTL_I915_PERF_ADD_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_ADD_CONFIG, struct drm_i915_perf_oa_config)
+#define DRM_IOCTL_I915_PERF_REMOVE_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_REMOVE_CONFIG, __u64)
 typedef struct drm_i915_batchbuffer {
   int start;
   int used;
@@ -292,6 +296,11 @@
 #define I915_PARAM_HUC_STATUS 42
 #define I915_PARAM_HAS_EXEC_ASYNC 43
 #define I915_PARAM_HAS_EXEC_FENCE 44
+#define I915_PARAM_HAS_EXEC_CAPTURE 45
+#define I915_PARAM_SLICE_MASK 46
+#define I915_PARAM_SUBSLICE_MASK 47
+#define I915_PARAM_HAS_EXEC_BATCH_FIRST 48
+#define I915_PARAM_HAS_EXEC_FENCE_ARRAY 49
 typedef struct drm_i915_getparam {
   __s32 param;
   int __user * value;
@@ -396,6 +405,7 @@
 #define I915_GEM_DOMAIN_INSTRUCTION 0x00000010
 #define I915_GEM_DOMAIN_VERTEX 0x00000020
 #define I915_GEM_DOMAIN_GTT 0x00000040
+#define I915_GEM_DOMAIN_WC 0x00000080
 struct drm_i915_gem_exec_object {
   __u32 handle;
   __u32 relocation_count;
@@ -426,7 +436,8 @@
 #define EXEC_OBJECT_PINNED (1 << 4)
 #define EXEC_OBJECT_PAD_TO_SIZE (1 << 5)
 #define EXEC_OBJECT_ASYNC (1 << 6)
-#define __EXEC_OBJECT_UNKNOWN_FLAGS - (EXEC_OBJECT_ASYNC << 1)
+#define EXEC_OBJECT_CAPTURE (1 << 7)
+#define __EXEC_OBJECT_UNKNOWN_FLAGS - (EXEC_OBJECT_CAPTURE << 1)
   __u64 flags;
   union {
     __u64 rsvd1;
@@ -434,6 +445,13 @@
   };
   __u64 rsvd2;
 };
+struct drm_i915_gem_exec_fence {
+  __u32 handle;
+#define I915_EXEC_FENCE_WAIT (1 << 0)
+#define I915_EXEC_FENCE_SIGNAL (1 << 1)
+#define __I915_EXEC_FENCE_UNKNOWN_FLAGS (- (I915_EXEC_FENCE_SIGNAL << 1))
+  __u32 flags;
+};
 struct drm_i915_gem_execbuffer2 {
   __u64 buffers_ptr;
   __u32 buffer_count;
@@ -470,7 +488,9 @@
 #define I915_EXEC_RESOURCE_STREAMER (1 << 15)
 #define I915_EXEC_FENCE_IN (1 << 16)
 #define I915_EXEC_FENCE_OUT (1 << 17)
-#define __I915_EXEC_UNKNOWN_FLAGS (- (I915_EXEC_FENCE_OUT << 1))
+#define I915_EXEC_BATCH_FIRST (1 << 18)
+#define I915_EXEC_FENCE_ARRAY (1 << 19)
+#define __I915_EXEC_UNKNOWN_FLAGS (- (I915_EXEC_FENCE_ARRAY << 1))
 #define I915_EXEC_CONTEXT_ID_MASK (0xffffffff)
 #define i915_execbuffer2_set_context_id(eb2,context) (eb2).rsvd1 = context & I915_EXEC_CONTEXT_ID_MASK
 #define i915_execbuffer2_get_context_id(eb2) ((eb2).rsvd1 & I915_EXEC_CONTEXT_ID_MASK)
@@ -650,6 +670,9 @@
   I915_OA_FORMAT_A45_B8_C8,
   I915_OA_FORMAT_B4_C8_A16,
   I915_OA_FORMAT_C4_B8,
+  I915_OA_FORMAT_A12,
+  I915_OA_FORMAT_A12_B8_C8,
+  I915_OA_FORMAT_A32u40_A4u32_B8_C8,
   I915_OA_FORMAT_MAX
 };
 enum drm_i915_perf_property_id {
@@ -681,6 +704,15 @@
   DRM_I915_PERF_RECORD_OA_BUFFER_LOST = 3,
   DRM_I915_PERF_RECORD_MAX
 };
+struct drm_i915_perf_oa_config {
+  char uuid[36];
+  __u32 n_mux_regs;
+  __u32 n_boolean_regs;
+  __u32 n_flex_regs;
+  __u64 __user mux_regs_ptr;
+  __u64 __user boolean_regs_ptr;
+  __u64 __user flex_regs_ptr;
+};
 #ifdef __cplusplus
 #endif
 #endif
diff --git a/libc/kernel/uapi/drm/msm_drm.h b/libc/kernel/uapi/drm/msm_drm.h
index 83ad769..4f1a423 100644
--- a/libc/kernel/uapi/drm/msm_drm.h
+++ b/libc/kernel/uapi/drm/msm_drm.h
@@ -55,9 +55,11 @@
   __u32 flags;
   __u32 handle;
 };
+#define MSM_INFO_IOVA 0x01
+#define MSM_INFO_FLAGS (MSM_INFO_IOVA)
 struct drm_msm_gem_info {
   __u32 handle;
-  __u32 pad;
+  __u32 flags;
   __u64 offset;
 };
 #define MSM_PREP_READ 0x01
@@ -89,7 +91,7 @@
   __u32 size;
   __u32 pad;
   __u32 nr_relocs;
-  __u64 __user relocs;
+  __u64 relocs;
 };
 #define MSM_SUBMIT_BO_READ 0x0001
 #define MSM_SUBMIT_BO_WRITE 0x0002
@@ -108,8 +110,8 @@
   __u32 fence;
   __u32 nr_bos;
   __u32 nr_cmds;
-  __u64 __user bos;
-  __u64 __user cmds;
+  __u64 bos;
+  __u64 cmds;
   __s32 fence_fd;
 };
 struct drm_msm_wait_fence {
@@ -133,7 +135,6 @@
 #define DRM_MSM_GEM_SUBMIT 0x06
 #define DRM_MSM_WAIT_FENCE 0x07
 #define DRM_MSM_GEM_MADVISE 0x08
-#define DRM_MSM_NUM_IOCTLS 0x09
 #define DRM_IOCTL_MSM_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GET_PARAM, struct drm_msm_param)
 #define DRM_IOCTL_MSM_GEM_NEW DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GEM_NEW, struct drm_msm_gem_new)
 #define DRM_IOCTL_MSM_GEM_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GEM_INFO, struct drm_msm_gem_info)
diff --git a/libc/kernel/uapi/drm/qxl_drm.h b/libc/kernel/uapi/drm/qxl_drm.h
index c1966ae..5942635 100644
--- a/libc/kernel/uapi/drm/qxl_drm.h
+++ b/libc/kernel/uapi/drm/qxl_drm.h
@@ -51,8 +51,8 @@
   __u32 pad;
 };
 struct drm_qxl_command {
-  __u64 __user command;
-  __u64 __user relocs;
+  __u64 command;
+  __u64 relocs;
   __u32 type;
   __u32 command_size;
   __u32 relocs_num;
@@ -61,7 +61,7 @@
 struct drm_qxl_execbuffer {
   __u32 flags;
   __u32 commands_num;
-  __u64 __user commands;
+  __u64 commands;
 };
 struct drm_qxl_update_area {
   __u32 handle;
diff --git a/libc/kernel/uapi/drm/vc4_drm.h b/libc/kernel/uapi/drm/vc4_drm.h
index 8c59253..d96c49d 100644
--- a/libc/kernel/uapi/drm/vc4_drm.h
+++ b/libc/kernel/uapi/drm/vc4_drm.h
@@ -29,6 +29,9 @@
 #define DRM_VC4_CREATE_SHADER_BO 0x05
 #define DRM_VC4_GET_HANG_STATE 0x06
 #define DRM_VC4_GET_PARAM 0x07
+#define DRM_VC4_SET_TILING 0x08
+#define DRM_VC4_GET_TILING 0x09
+#define DRM_VC4_LABEL_BO 0x0a
 #define DRM_IOCTL_VC4_SUBMIT_CL DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_SUBMIT_CL, struct drm_vc4_submit_cl)
 #define DRM_IOCTL_VC4_WAIT_SEQNO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_WAIT_SEQNO, struct drm_vc4_wait_seqno)
 #define DRM_IOCTL_VC4_WAIT_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_WAIT_BO, struct drm_vc4_wait_bo)
@@ -37,6 +40,9 @@
 #define DRM_IOCTL_VC4_CREATE_SHADER_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_CREATE_SHADER_BO, struct drm_vc4_create_shader_bo)
 #define DRM_IOCTL_VC4_GET_HANG_STATE DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GET_HANG_STATE, struct drm_vc4_get_hang_state)
 #define DRM_IOCTL_VC4_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GET_PARAM, struct drm_vc4_get_param)
+#define DRM_IOCTL_VC4_SET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_SET_TILING, struct drm_vc4_set_tiling)
+#define DRM_IOCTL_VC4_GET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GET_TILING, struct drm_vc4_get_tiling)
+#define DRM_IOCTL_VC4_LABEL_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_LABEL_BO, struct drm_vc4_label_bo)
 struct drm_vc4_submit_rcl_surface {
   __u32 hindex;
   __u32 offset;
@@ -71,6 +77,9 @@
   __u8 clear_s;
   __u32 pad : 24;
 #define VC4_SUBMIT_CL_USE_CLEAR_COLOR (1 << 0)
+#define VC4_SUBMIT_CL_FIXED_RCL_ORDER (1 << 1)
+#define VC4_SUBMIT_CL_RCL_ORDER_INCREASING_X (1 << 2)
+#define VC4_SUBMIT_CL_RCL_ORDER_INCREASING_Y (1 << 3)
   __u32 flags;
   __u64 seqno;
 };
@@ -132,11 +141,27 @@
 #define DRM_VC4_PARAM_SUPPORTS_BRANCHES 3
 #define DRM_VC4_PARAM_SUPPORTS_ETC1 4
 #define DRM_VC4_PARAM_SUPPORTS_THREADED_FS 5
+#define DRM_VC4_PARAM_SUPPORTS_FIXED_RCL_ORDER 6
 struct drm_vc4_get_param {
   __u32 param;
   __u32 pad;
   __u64 value;
 };
+struct drm_vc4_get_tiling {
+  __u32 handle;
+  __u32 flags;
+  __u64 modifier;
+};
+struct drm_vc4_set_tiling {
+  __u32 handle;
+  __u32 flags;
+  __u64 modifier;
+};
+struct drm_vc4_label_bo {
+  __u32 handle;
+  __u32 len;
+  __u64 name;
+};
 #ifdef __cplusplus
 #endif
 #endif
diff --git a/libc/kernel/uapi/drm/vmwgfx_drm.h b/libc/kernel/uapi/drm/vmwgfx_drm.h
index 2b7e0fe..f6a7b14 100644
--- a/libc/kernel/uapi/drm/vmwgfx_drm.h
+++ b/libc/kernel/uapi/drm/vmwgfx_drm.h
@@ -104,6 +104,8 @@
   struct drm_vmw_surface_arg req;
 };
 #define DRM_VMW_EXECBUF_VERSION 2
+#define DRM_VMW_EXECBUF_FLAG_IMPORT_FENCE_FD (1 << 0)
+#define DRM_VMW_EXECBUF_FLAG_EXPORT_FENCE_FD (1 << 1)
 struct drm_vmw_execbuf_arg {
   __u64 commands;
   __u32 command_size;
@@ -112,14 +114,14 @@
   __u32 version;
   __u32 flags;
   __u32 context_handle;
-  __u32 pad64;
+  __s32 imported_fence_fd;
 };
 struct drm_vmw_fence_rep {
   __u32 handle;
   __u32 mask;
   __u32 seqno;
   __u32 passed_seqno;
-  __u32 pad64;
+  __s32 fd;
   __s32 error;
 };
 struct drm_vmw_alloc_dmabuf_req {
diff --git a/libc/kernel/uapi/linux/aio_abi.h b/libc/kernel/uapi/linux/aio_abi.h
index 2a7a6e7..e71936d 100644
--- a/libc/kernel/uapi/linux/aio_abi.h
+++ b/libc/kernel/uapi/linux/aio_abi.h
@@ -19,6 +19,7 @@
 #ifndef __LINUX__AIO_ABI_H
 #define __LINUX__AIO_ABI_H
 #include <linux/types.h>
+#include <linux/fs.h>
 #include <asm/byteorder.h>
 typedef __kernel_ulong_t aio_context_t;
 enum {
@@ -37,16 +38,17 @@
   __s64 res;
   __s64 res2;
 };
+struct iocb {
+  __u64 aio_data;
 #if defined(__BYTE_ORDER) ? __BYTE_ORDER == __LITTLE_ENDIAN : defined(__LITTLE_ENDIAN)
-#define PADDED(x,y) x, y
+  __u32 aio_key;
+  __kernel_rwf_t aio_rw_flags;
 #elif defined(__BYTE_ORDER)?__BYTE_ORDER==__BIG_ENDIAN:defined(__BIG_ENDIAN)
-#define PADDED(x,y) y, x
+  __kernel_rwf_t aio_rw_flags;
+  __u32 aio_key;
 #else
 #error edit for your odd byteorder .
 #endif
-struct iocb {
-  __u64 aio_data;
-  __u32 PADDED(aio_key, aio_reserved1);
   __u16 aio_lio_opcode;
   __s16 aio_reqprio;
   __u32 aio_fildes;
diff --git a/libc/kernel/uapi/linux/android/binder.h b/libc/kernel/uapi/linux/android/binder.h
index 717826d..538a441 100644
--- a/libc/kernel/uapi/linux/android/binder.h
+++ b/libc/kernel/uapi/linux/android/binder.h
@@ -74,8 +74,9 @@
 enum {
   BINDER_BUFFER_FLAG_HAS_PARENT = 0x01,
 };
-struct __kernel_binder_fd_array_object {
+struct binder_fd_array_object {
   struct binder_object_header hdr;
+  __u32 pad;
   binder_size_t num_fds;
   binder_size_t parent;
   binder_size_t parent_offset;
@@ -96,6 +97,12 @@
 #else
 #define BINDER_CURRENT_PROTOCOL_VERSION 8
 #endif
+struct binder_node_debug_info {
+  binder_uintptr_t ptr;
+  binder_uintptr_t cookie;
+  __u32 has_strong_ref;
+  __u32 has_weak_ref;
+};
 #define BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read)
 #define BINDER_SET_IDLE_TIMEOUT _IOW('b', 3, __s64)
 #define BINDER_SET_MAX_THREADS _IOW('b', 5, __u32)
@@ -103,6 +110,7 @@
 #define BINDER_SET_CONTEXT_MGR _IOW('b', 7, __s32)
 #define BINDER_THREAD_EXIT _IOW('b', 8, __s32)
 #define BINDER_VERSION _IOWR('b', 9, struct binder_version)
+#define BINDER_GET_NODE_DEBUG_INFO _IOWR('b', 11, struct binder_node_debug_info)
 enum transaction_flags {
   TF_ONE_WAY = 0x01,
   TF_ROOT_OBJECT = 0x04,
diff --git a/libc/kernel/uapi/linux/auto_dev-ioctl.h b/libc/kernel/uapi/linux/auto_dev-ioctl.h
index be00b9e..23c8096 100644
--- a/libc/kernel/uapi/linux/auto_dev-ioctl.h
+++ b/libc/kernel/uapi/linux/auto_dev-ioctl.h
@@ -22,7 +22,7 @@
 #include <linux/string.h>
 #define AUTOFS_DEVICE_NAME "autofs"
 #define AUTOFS_DEV_IOCTL_VERSION_MAJOR 1
-#define AUTOFS_DEV_IOCTL_VERSION_MINOR 0
+#define AUTOFS_DEV_IOCTL_VERSION_MINOR 1
 #define AUTOFS_DEV_IOCTL_SIZE sizeof(struct autofs_dev_ioctl)
 struct args_protover {
   __u32 version;
diff --git a/libc/kernel/uapi/linux/auto_fs4.h b/libc/kernel/uapi/linux/auto_fs4.h
index d09b39b..be6766b 100644
--- a/libc/kernel/uapi/linux/auto_fs4.h
+++ b/libc/kernel/uapi/linux/auto_fs4.h
@@ -85,8 +85,6 @@
   AUTOFS_IOC_ASKUMOUNT_CMD = 0x70,
 };
 #define AUTOFS_IOC_EXPIRE_MULTI _IOW(AUTOFS_IOCTL, AUTOFS_IOC_EXPIRE_MULTI_CMD, int)
-#define AUTOFS_IOC_EXPIRE_INDIRECT AUTOFS_IOC_EXPIRE_MULTI
-#define AUTOFS_IOC_EXPIRE_DIRECT AUTOFS_IOC_EXPIRE_MULTI
 #define AUTOFS_IOC_PROTOSUBVER _IOR(AUTOFS_IOCTL, AUTOFS_IOC_PROTOSUBVER_CMD, int)
 #define AUTOFS_IOC_ASKUMOUNT _IOR(AUTOFS_IOCTL, AUTOFS_IOC_ASKUMOUNT_CMD, int)
 #endif
diff --git a/libc/kernel/uapi/linux/blktrace_api.h b/libc/kernel/uapi/linux/blktrace_api.h
index a6129f8..64c0b77 100644
--- a/libc/kernel/uapi/linux/blktrace_api.h
+++ b/libc/kernel/uapi/linux/blktrace_api.h
@@ -59,11 +59,13 @@
   __BLK_TA_REMAP,
   __BLK_TA_ABORT,
   __BLK_TA_DRV_DATA,
+  __BLK_TA_CGROUP = 1 << 8,
 };
 enum blktrace_notify {
   __BLK_TN_PROCESS = 0,
   __BLK_TN_TIMESTAMP,
   __BLK_TN_MESSAGE,
+  __BLK_TN_CGROUP = __BLK_TA_CGROUP,
 };
 #define BLK_TA_QUEUE (__BLK_TA_QUEUE | BLK_TC_ACT(BLK_TC_QUEUE))
 #define BLK_TA_BACKMERGE (__BLK_TA_BACKMERGE | BLK_TC_ACT(BLK_TC_QUEUE))
diff --git a/libc/kernel/uapi/linux/bpf.h b/libc/kernel/uapi/linux/bpf.h
index 08c1aba..1dfb99f 100644
--- a/libc/kernel/uapi/linux/bpf.h
+++ b/libc/kernel/uapi/linux/bpf.h
@@ -31,8 +31,12 @@
 #define BPF_FROM_LE BPF_TO_LE
 #define BPF_FROM_BE BPF_TO_BE
 #define BPF_JNE 0x50
+#define BPF_JLT 0xa0
+#define BPF_JLE 0xb0
 #define BPF_JSGT 0x60
 #define BPF_JSGE 0x70
+#define BPF_JSLT 0xc0
+#define BPF_JSLE 0xd0
 #define BPF_CALL 0x80
 #define BPF_EXIT 0x90
 enum {
@@ -73,6 +77,11 @@
   BPF_PROG_ATTACH,
   BPF_PROG_DETACH,
   BPF_PROG_TEST_RUN,
+  BPF_PROG_GET_NEXT_ID,
+  BPF_MAP_GET_NEXT_ID,
+  BPF_PROG_GET_FD_BY_ID,
+  BPF_MAP_GET_FD_BY_ID,
+  BPF_OBJ_GET_INFO_BY_FD,
 };
 enum bpf_map_type {
   BPF_MAP_TYPE_UNSPEC,
@@ -89,6 +98,8 @@
   BPF_MAP_TYPE_LPM_TRIE,
   BPF_MAP_TYPE_ARRAY_OF_MAPS,
   BPF_MAP_TYPE_HASH_OF_MAPS,
+  BPF_MAP_TYPE_DEVMAP,
+  BPF_MAP_TYPE_SOCKMAP,
 };
 enum bpf_prog_type {
   BPF_PROG_TYPE_UNSPEC,
@@ -104,11 +115,16 @@
   BPF_PROG_TYPE_LWT_IN,
   BPF_PROG_TYPE_LWT_OUT,
   BPF_PROG_TYPE_LWT_XMIT,
+  BPF_PROG_TYPE_SOCK_OPS,
+  BPF_PROG_TYPE_SK_SKB,
 };
 enum bpf_attach_type {
   BPF_CGROUP_INET_INGRESS,
   BPF_CGROUP_INET_EGRESS,
   BPF_CGROUP_INET_SOCK_CREATE,
+  BPF_CGROUP_SOCK_OPS,
+  BPF_SK_SKB_STREAM_PARSER,
+  BPF_SK_SKB_STREAM_VERDICT,
   __MAX_BPF_ATTACH_TYPE
 };
 #define MAX_BPF_ATTACH_TYPE __MAX_BPF_ATTACH_TYPE
@@ -120,6 +136,7 @@
 #define BPF_EXIST 2
 #define BPF_F_NO_PREALLOC (1U << 0)
 #define BPF_F_NO_COMMON_LRU (1U << 1)
+#define BPF_F_NUMA_NODE (1U << 2)
 union bpf_attr {
   struct {
     __u32 map_type;
@@ -128,6 +145,7 @@
     __u32 max_entries;
     __u32 map_flags;
     __u32 inner_map_fd;
+    __u32 numa_node;
   };
   struct {
     __u32 map_fd;
@@ -169,8 +187,21 @@
     __u32 repeat;
     __u32 duration;
   } test;
+  struct {
+    union {
+      __u32 start_id;
+      __u32 prog_id;
+      __u32 map_id;
+    };
+    __u32 next_id;
+  };
+  struct {
+    __u32 bpf_fd;
+    __u32 info_len;
+    __aligned_u64 info;
+  } info;
 } __attribute__((aligned(8)));
-#define __BPF_FUNC_MAPPER(FN) FN(unspec), FN(map_lookup_elem), FN(map_update_elem), FN(map_delete_elem), FN(probe_read), FN(ktime_get_ns), FN(trace_printk), FN(get_prandom_u32), FN(get_smp_processor_id), FN(skb_store_bytes), FN(l3_csum_replace), FN(l4_csum_replace), FN(tail_call), FN(clone_redirect), FN(get_current_pid_tgid), FN(get_current_uid_gid), FN(get_current_comm), FN(get_cgroup_classid), FN(skb_vlan_push), FN(skb_vlan_pop), FN(skb_get_tunnel_key), FN(skb_set_tunnel_key), FN(perf_event_read), FN(redirect), FN(get_route_realm), FN(perf_event_output), FN(skb_load_bytes), FN(get_stackid), FN(csum_diff), FN(skb_get_tunnel_opt), FN(skb_set_tunnel_opt), FN(skb_change_proto), FN(skb_change_type), FN(skb_under_cgroup), FN(get_hash_recalc), FN(get_current_task), FN(probe_write_user), FN(current_task_under_cgroup), FN(skb_change_tail), FN(skb_pull_data), FN(csum_update), FN(set_hash_invalid), FN(get_numa_node_id), FN(skb_change_head), FN(xdp_adjust_head), FN(probe_read_str), FN(get_socket_cookie), FN(get_socket_uid),
+#define __BPF_FUNC_MAPPER(FN) FN(unspec), FN(map_lookup_elem), FN(map_update_elem), FN(map_delete_elem), FN(probe_read), FN(ktime_get_ns), FN(trace_printk), FN(get_prandom_u32), FN(get_smp_processor_id), FN(skb_store_bytes), FN(l3_csum_replace), FN(l4_csum_replace), FN(tail_call), FN(clone_redirect), FN(get_current_pid_tgid), FN(get_current_uid_gid), FN(get_current_comm), FN(get_cgroup_classid), FN(skb_vlan_push), FN(skb_vlan_pop), FN(skb_get_tunnel_key), FN(skb_set_tunnel_key), FN(perf_event_read), FN(redirect), FN(get_route_realm), FN(perf_event_output), FN(skb_load_bytes), FN(get_stackid), FN(csum_diff), FN(skb_get_tunnel_opt), FN(skb_set_tunnel_opt), FN(skb_change_proto), FN(skb_change_type), FN(skb_under_cgroup), FN(get_hash_recalc), FN(get_current_task), FN(probe_write_user), FN(current_task_under_cgroup), FN(skb_change_tail), FN(skb_pull_data), FN(csum_update), FN(set_hash_invalid), FN(get_numa_node_id), FN(skb_change_head), FN(xdp_adjust_head), FN(probe_read_str), FN(get_socket_cookie), FN(get_socket_uid), FN(set_hash), FN(setsockopt), FN(skb_adjust_room), FN(redirect_map), FN(sk_redirect_map), FN(sock_map_update),
 #define __BPF_ENUM_FN(x) BPF_FUNC_ ##x
 enum bpf_func_id {
   __BPF_FUNC_MAPPER(__BPF_ENUM_FN) __BPF_FUNC_MAX_ID,
@@ -193,6 +224,9 @@
 #define BPF_F_INDEX_MASK 0xffffffffULL
 #define BPF_F_CURRENT_CPU BPF_F_INDEX_MASK
 #define BPF_F_CTXLEN_MASK (0xfffffULL << 32)
+enum bpf_adj_room_mode {
+  BPF_ADJ_ROOM_NET,
+};
 struct __sk_buff {
   __u32 len;
   __u32 pkt_type;
@@ -212,6 +246,13 @@
   __u32 data;
   __u32 data_end;
   __u32 napi_id;
+  __u32 family;
+  __u32 remote_ip4;
+  __u32 local_ip4;
+  __u32 remote_ip6[4];
+  __u32 local_ip6[4];
+  __u32 remote_port;
+  __u32 local_port;
 };
 struct bpf_tunnel_key {
   __u32 tunnel_id;
@@ -234,6 +275,8 @@
   __u32 family;
   __u32 type;
   __u32 protocol;
+  __u32 mark;
+  __u32 priority;
 };
 #define XDP_PACKET_HEADROOM 256
 enum xdp_action {
@@ -241,9 +284,57 @@
   XDP_DROP,
   XDP_PASS,
   XDP_TX,
+  XDP_REDIRECT,
 };
 struct xdp_md {
   __u32 data;
   __u32 data_end;
 };
+enum sk_action {
+  SK_DROP = 0,
+  SK_PASS,
+};
+#define BPF_TAG_SIZE 8
+struct bpf_prog_info {
+  __u32 type;
+  __u32 id;
+  __u8 tag[BPF_TAG_SIZE];
+  __u32 jited_prog_len;
+  __u32 xlated_prog_len;
+  __aligned_u64 jited_prog_insns;
+  __aligned_u64 xlated_prog_insns;
+} __attribute__((aligned(8)));
+struct bpf_map_info {
+  __u32 type;
+  __u32 id;
+  __u32 key_size;
+  __u32 value_size;
+  __u32 max_entries;
+  __u32 map_flags;
+} __attribute__((aligned(8)));
+struct bpf_sock_ops {
+  __u32 op;
+  union {
+    __u32 reply;
+    __u32 replylong[4];
+  };
+  __u32 family;
+  __u32 remote_ip4;
+  __u32 local_ip4;
+  __u32 remote_ip6[4];
+  __u32 local_ip6[4];
+  __u32 remote_port;
+  __u32 local_port;
+};
+enum {
+  BPF_SOCK_OPS_VOID,
+  BPF_SOCK_OPS_TIMEOUT_INIT,
+  BPF_SOCK_OPS_RWND_INIT,
+  BPF_SOCK_OPS_TCP_CONNECT_CB,
+  BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB,
+  BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB,
+  BPF_SOCK_OPS_NEEDS_ECN,
+};
+#define TCP_BPF_IW 1001
+#define TCP_BPF_SNDCWND_CLAMP 1002
 #endif
diff --git a/libc/kernel/uapi/linux/btrfs.h b/libc/kernel/uapi/linux/btrfs.h
index 56e33ae..a23ab58 100644
--- a/libc/kernel/uapi/linux/btrfs.h
+++ b/libc/kernel/uapi/linux/btrfs.h
@@ -167,7 +167,7 @@
 #define BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL (1ULL << 1)
 #define BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS (1ULL << 2)
 #define BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO (1ULL << 3)
-#define BTRFS_FEATURE_INCOMPAT_COMPRESS_LZOv2 (1ULL << 4)
+#define BTRFS_FEATURE_INCOMPAT_COMPRESS_ZSTD (1ULL << 4)
 #define BTRFS_FEATURE_INCOMPAT_BIG_METADATA (1ULL << 5)
 #define BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF (1ULL << 6)
 #define BTRFS_FEATURE_INCOMPAT_RAID56 (1ULL << 7)
diff --git a/libc/kernel/uapi/linux/capability.h b/libc/kernel/uapi/linux/capability.h
index f414848..8ba448e 100644
--- a/libc/kernel/uapi/linux/capability.h
+++ b/libc/kernel/uapi/linux/capability.h
@@ -44,9 +44,12 @@
 #define VFS_CAP_REVISION_2 0x02000000
 #define VFS_CAP_U32_2 2
 #define XATTR_CAPS_SZ_2 (sizeof(__le32) * (1 + 2 * VFS_CAP_U32_2))
-#define XATTR_CAPS_SZ XATTR_CAPS_SZ_2
-#define VFS_CAP_U32 VFS_CAP_U32_2
-#define VFS_CAP_REVISION VFS_CAP_REVISION_2
+#define VFS_CAP_REVISION_3 0x03000000
+#define VFS_CAP_U32_3 2
+#define XATTR_CAPS_SZ_3 (sizeof(__le32) * (2 + 2 * VFS_CAP_U32_3))
+#define XATTR_CAPS_SZ XATTR_CAPS_SZ_3
+#define VFS_CAP_U32 VFS_CAP_U32_3
+#define VFS_CAP_REVISION VFS_CAP_REVISION_3
 struct vfs_cap_data {
   __le32 magic_etc;
   struct {
@@ -54,6 +57,14 @@
     __le32 inheritable;
   } data[VFS_CAP_U32];
 };
+struct vfs_ns_cap_data {
+  __le32 magic_etc;
+  struct {
+    __le32 permitted;
+    __le32 inheritable;
+  } data[VFS_CAP_U32];
+  __le32 rootid;
+};
 #define _LINUX_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_1
 #define _LINUX_CAPABILITY_U32S _LINUX_CAPABILITY_U32S_1
 #define CAP_CHOWN 0
diff --git a/libc/kernel/uapi/linux/cec.h b/libc/kernel/uapi/linux/cec.h
index 8125ac4..3fcee96 100644
--- a/libc/kernel/uapi/linux/cec.h
+++ b/libc/kernel/uapi/linux/cec.h
@@ -91,6 +91,7 @@
 #define CEC_MODE_FOLLOWER (0x1 << 4)
 #define CEC_MODE_EXCL_FOLLOWER (0x2 << 4)
 #define CEC_MODE_EXCL_FOLLOWER_PASSTHRU (0x3 << 4)
+#define CEC_MODE_MONITOR_PIN (0xd << 4)
 #define CEC_MODE_MONITOR (0xe << 4)
 #define CEC_MODE_MONITOR_ALL (0xf << 4)
 #define CEC_MODE_FOLLOWER_MSK 0xf0
@@ -100,6 +101,8 @@
 #define CEC_CAP_PASSTHROUGH (1 << 3)
 #define CEC_CAP_RC (1 << 4)
 #define CEC_CAP_MONITOR_ALL (1 << 5)
+#define CEC_CAP_NEEDS_HPD (1 << 6)
+#define CEC_CAP_MONITOR_PIN (1 << 7)
 struct cec_caps {
   char driver[32];
   char name[32];
@@ -125,7 +128,10 @@
 #define CEC_LOG_ADDRS_FL_CDC_ONLY (1 << 2)
 #define CEC_EVENT_STATE_CHANGE 1
 #define CEC_EVENT_LOST_MSGS 2
+#define CEC_EVENT_PIN_CEC_LOW 3
+#define CEC_EVENT_PIN_CEC_HIGH 4
 #define CEC_EVENT_FL_INITIAL_STATE (1 << 0)
+#define CEC_EVENT_FL_DROPPED_EVENTS (1 << 1)
 struct cec_event_state_change {
   __u16 phys_addr;
   __u16 log_addr_mask;
diff --git a/libc/kernel/uapi/linux/devlink.h b/libc/kernel/uapi/linux/devlink.h
index 01f6e74..1d5c43c 100644
--- a/libc/kernel/uapi/linux/devlink.h
+++ b/libc/kernel/uapi/linux/devlink.h
@@ -168,4 +168,18 @@
 enum devlink_dpipe_action_type {
   DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY,
 };
+enum devlink_dpipe_field_ethernet_id {
+  DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC,
+};
+enum devlink_dpipe_field_ipv4_id {
+  DEVLINK_DPIPE_FIELD_IPV4_DST_IP,
+};
+enum devlink_dpipe_field_ipv6_id {
+  DEVLINK_DPIPE_FIELD_IPV6_DST_IP,
+};
+enum devlink_dpipe_header_id {
+  DEVLINK_DPIPE_HEADER_ETHERNET,
+  DEVLINK_DPIPE_HEADER_IPV4,
+  DEVLINK_DPIPE_HEADER_IPV6,
+};
 #endif
diff --git a/libc/kernel/uapi/linux/dlm_netlink.h b/libc/kernel/uapi/linux/dlm_netlink.h
index 64e5d1e..0c655fa 100644
--- a/libc/kernel/uapi/linux/dlm_netlink.h
+++ b/libc/kernel/uapi/linux/dlm_netlink.h
@@ -19,6 +19,7 @@
 #ifndef _DLM_NETLINK_H
 #define _DLM_NETLINK_H
 #include <linux/types.h>
+#include <linux/dlmconstants.h>
 enum {
   DLM_STATUS_WAITING = 1,
   DLM_STATUS_GRANTED = 2,
diff --git a/libc/kernel/uapi/linux/dm-ioctl.h b/libc/kernel/uapi/linux/dm-ioctl.h
index a418ea0..cc340b5 100644
--- a/libc/kernel/uapi/linux/dm-ioctl.h
+++ b/libc/kernel/uapi/linux/dm-ioctl.h
@@ -80,7 +80,8 @@
   DM_TABLE_STATUS_CMD,
   DM_LIST_VERSIONS_CMD,
   DM_TARGET_MSG_CMD,
-  DM_DEV_SET_GEOMETRY_CMD
+  DM_DEV_SET_GEOMETRY_CMD,
+  DM_DEV_ARM_POLL_CMD,
 };
 #define DM_IOCTL 0xfd
 #define DM_VERSION _IOWR(DM_IOCTL, DM_VERSION_CMD, struct dm_ioctl)
@@ -92,6 +93,7 @@
 #define DM_DEV_SUSPEND _IOWR(DM_IOCTL, DM_DEV_SUSPEND_CMD, struct dm_ioctl)
 #define DM_DEV_STATUS _IOWR(DM_IOCTL, DM_DEV_STATUS_CMD, struct dm_ioctl)
 #define DM_DEV_WAIT _IOWR(DM_IOCTL, DM_DEV_WAIT_CMD, struct dm_ioctl)
+#define DM_DEV_ARM_POLL _IOWR(DM_IOCTL, DM_DEV_ARM_POLL_CMD, struct dm_ioctl)
 #define DM_TABLE_LOAD _IOWR(DM_IOCTL, DM_TABLE_LOAD_CMD, struct dm_ioctl)
 #define DM_TABLE_CLEAR _IOWR(DM_IOCTL, DM_TABLE_CLEAR_CMD, struct dm_ioctl)
 #define DM_TABLE_DEPS _IOWR(DM_IOCTL, DM_TABLE_DEPS_CMD, struct dm_ioctl)
@@ -100,9 +102,9 @@
 #define DM_TARGET_MSG _IOWR(DM_IOCTL, DM_TARGET_MSG_CMD, struct dm_ioctl)
 #define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)
 #define DM_VERSION_MAJOR 4
-#define DM_VERSION_MINOR 35
+#define DM_VERSION_MINOR 37
 #define DM_VERSION_PATCHLEVEL 0
-#define DM_VERSION_EXTRA "-ioctl(2016-06-23)"
+#define DM_VERSION_EXTRA "-ioctl(2017-09-20)"
 #define DM_READONLY_FLAG (1 << 0)
 #define DM_SUSPEND_FLAG (1 << 1)
 #define DM_PERSISTENT_DEV_FLAG (1 << 3)
diff --git a/libc/kernel/uapi/linux/dvb/ca.h b/libc/kernel/uapi/linux/dvb/ca.h
index c494ad5..fa977c7 100644
--- a/libc/kernel/uapi/linux/dvb/ca.h
+++ b/libc/kernel/uapi/linux/dvb/ca.h
@@ -18,7 +18,7 @@
  ****************************************************************************/
 #ifndef _DVBCA_H_
 #define _DVBCA_H_
-typedef struct ca_slot_info {
+struct ca_slot_info {
   int num;
   int type;
 #define CA_CI 1
@@ -29,41 +29,41 @@
   unsigned int flags;
 #define CA_CI_MODULE_PRESENT 1
 #define CA_CI_MODULE_READY 2
-} ca_slot_info_t;
-typedef struct ca_descr_info {
+};
+struct ca_descr_info {
   unsigned int num;
   unsigned int type;
 #define CA_ECD 1
 #define CA_NDS 2
 #define CA_DSS 4
-} ca_descr_info_t;
-typedef struct ca_caps {
+};
+struct ca_caps {
   unsigned int slot_num;
   unsigned int slot_type;
   unsigned int descr_num;
   unsigned int descr_type;
-} ca_caps_t;
-typedef struct ca_msg {
+};
+struct ca_msg {
   unsigned int index;
   unsigned int type;
   unsigned int length;
   unsigned char msg[256];
-} ca_msg_t;
-typedef struct ca_descr {
+};
+struct ca_descr {
   unsigned int index;
   unsigned int parity;
   unsigned char cw[8];
-} ca_descr_t;
-typedef struct ca_pid {
-  unsigned int pid;
-  int index;
-} ca_pid_t;
+};
 #define CA_RESET _IO('o', 128)
-#define CA_GET_CAP _IOR('o', 129, ca_caps_t)
-#define CA_GET_SLOT_INFO _IOR('o', 130, ca_slot_info_t)
-#define CA_GET_DESCR_INFO _IOR('o', 131, ca_descr_info_t)
-#define CA_GET_MSG _IOR('o', 132, ca_msg_t)
-#define CA_SEND_MSG _IOW('o', 133, ca_msg_t)
-#define CA_SET_DESCR _IOW('o', 134, ca_descr_t)
-#define CA_SET_PID _IOW('o', 135, ca_pid_t)
+#define CA_GET_CAP _IOR('o', 129, struct ca_caps)
+#define CA_GET_SLOT_INFO _IOR('o', 130, struct ca_slot_info)
+#define CA_GET_DESCR_INFO _IOR('o', 131, struct ca_descr_info)
+#define CA_GET_MSG _IOR('o', 132, struct ca_msg)
+#define CA_SEND_MSG _IOW('o', 133, struct ca_msg)
+#define CA_SET_DESCR _IOW('o', 134, struct ca_descr)
+typedef struct ca_slot_info ca_slot_info_t;
+typedef struct ca_descr_info ca_descr_info_t;
+typedef struct ca_caps ca_caps_t;
+typedef struct ca_msg ca_msg_t;
+typedef struct ca_descr ca_descr_t;
 #endif
diff --git a/libc/kernel/uapi/linux/dvb/dmx.h b/libc/kernel/uapi/linux/dvb/dmx.h
index 438c832..d4ea26e 100644
--- a/libc/kernel/uapi/linux/dvb/dmx.h
+++ b/libc/kernel/uapi/linux/dvb/dmx.h
@@ -27,12 +27,11 @@
   DMX_OUT_TS_TAP,
   DMX_OUT_TSDEMUX_TAP
 };
-typedef enum dmx_output dmx_output_t;
-typedef enum dmx_input {
+enum dmx_input {
   DMX_IN_FRONTEND,
   DMX_IN_DVR
-} dmx_input_t;
-typedef enum dmx_ts_pes {
+};
+enum dmx_ts_pes {
   DMX_PES_AUDIO0,
   DMX_PES_VIDEO0,
   DMX_PES_TELETEXT0,
@@ -54,48 +53,33 @@
   DMX_PES_SUBTITLE3,
   DMX_PES_PCR3,
   DMX_PES_OTHER
-} dmx_pes_type_t;
+};
 #define DMX_PES_AUDIO DMX_PES_AUDIO0
 #define DMX_PES_VIDEO DMX_PES_VIDEO0
 #define DMX_PES_TELETEXT DMX_PES_TELETEXT0
 #define DMX_PES_SUBTITLE DMX_PES_SUBTITLE0
 #define DMX_PES_PCR DMX_PES_PCR0
-typedef struct dmx_filter {
+struct dmx_filter {
   __u8 filter[DMX_FILTER_SIZE];
   __u8 mask[DMX_FILTER_SIZE];
   __u8 mode[DMX_FILTER_SIZE];
-} dmx_filter_t;
+};
 struct dmx_sct_filter_params {
   __u16 pid;
-  dmx_filter_t filter;
+  struct dmx_filter filter;
   __u32 timeout;
   __u32 flags;
 #define DMX_CHECK_CRC 1
 #define DMX_ONESHOT 2
 #define DMX_IMMEDIATE_START 4
-#define DMX_KERNEL_CLIENT 0x8000
 };
 struct dmx_pes_filter_params {
   __u16 pid;
-  dmx_input_t input;
-  dmx_output_t output;
-  dmx_pes_type_t pes_type;
+  enum dmx_input input;
+  enum dmx_output output;
+  enum dmx_ts_pes pes_type;
   __u32 flags;
 };
-typedef struct dmx_caps {
-  __u32 caps;
-  int num_decoders;
-} dmx_caps_t;
-typedef enum dmx_source {
-  DMX_SOURCE_FRONT0 = 0,
-  DMX_SOURCE_FRONT1,
-  DMX_SOURCE_FRONT2,
-  DMX_SOURCE_FRONT3,
-  DMX_SOURCE_DVR0 = 16,
-  DMX_SOURCE_DVR1,
-  DMX_SOURCE_DVR2,
-  DMX_SOURCE_DVR3
-} dmx_source_t;
 struct dmx_stc {
   unsigned int num;
   unsigned int base;
@@ -107,9 +91,11 @@
 #define DMX_SET_PES_FILTER _IOW('o', 44, struct dmx_pes_filter_params)
 #define DMX_SET_BUFFER_SIZE _IO('o', 45)
 #define DMX_GET_PES_PIDS _IOR('o', 47, __u16[5])
-#define DMX_GET_CAPS _IOR('o', 48, dmx_caps_t)
-#define DMX_SET_SOURCE _IOW('o', 49, dmx_source_t)
 #define DMX_GET_STC _IOWR('o', 50, struct dmx_stc)
 #define DMX_ADD_PID _IOW('o', 51, __u16)
 #define DMX_REMOVE_PID _IOW('o', 52, __u16)
+typedef enum dmx_output dmx_output_t;
+typedef enum dmx_input dmx_input_t;
+typedef enum dmx_ts_pes dmx_pes_type_t;
+typedef struct dmx_filter dmx_filter_t;
 #endif
diff --git a/libc/kernel/uapi/linux/dvb/frontend.h b/libc/kernel/uapi/linux/dvb/frontend.h
index 387e3f1..c8a48c1 100644
--- a/libc/kernel/uapi/linux/dvb/frontend.h
+++ b/libc/kernel/uapi/linux/dvb/frontend.h
@@ -19,12 +19,6 @@
 #ifndef _DVBFRONTEND_H_
 #define _DVBFRONTEND_H_
 #include <linux/types.h>
-enum fe_type {
-  FE_QPSK,
-  FE_QAM,
-  FE_OFDM,
-  FE_ATSC
-};
 enum fe_caps {
   FE_IS_STUPID = 0,
   FE_CAN_INVERSION_AUTO = 0x1,
@@ -58,6 +52,12 @@
   FE_CAN_RECOVER = 0x40000000,
   FE_CAN_MUTE_TS = 0x80000000
 };
+enum fe_type {
+  FE_QPSK,
+  FE_QAM,
+  FE_OFDM,
+  FE_ATSC
+};
 struct dvb_frontend_info {
   char name[128];
   enum fe_type type;
@@ -94,6 +94,7 @@
   SEC_MINI_B
 };
 enum fe_status {
+  FE_NONE = 0x00,
   FE_HAS_SIGNAL = 0x01,
   FE_HAS_CARRIER = 0x02,
   FE_HAS_VITERBI = 0x04,
@@ -308,13 +309,6 @@
 };
 #define NO_STREAM_ID_FILTER (~0U)
 #define LNA_AUTO (~0U)
-struct dtv_cmds_h {
-  char * name;
-  __u32 cmd;
-  __u32 set : 1;
-  __u32 buffer : 1;
-  __u32 reserved : 30;
-};
 enum fecap_scale_params {
   FE_SCALE_NOT_AVAILABLE = 0,
   FE_SCALE_DECIBEL,
@@ -353,6 +347,25 @@
   __u32 num;
   struct dtv_property * props;
 };
+#define FE_TUNE_MODE_ONESHOT 0x01
+#define FE_GET_INFO _IOR('o', 61, struct dvb_frontend_info)
+#define FE_DISEQC_RESET_OVERLOAD _IO('o', 62)
+#define FE_DISEQC_SEND_MASTER_CMD _IOW('o', 63, struct dvb_diseqc_master_cmd)
+#define FE_DISEQC_RECV_SLAVE_REPLY _IOR('o', 64, struct dvb_diseqc_slave_reply)
+#define FE_DISEQC_SEND_BURST _IO('o', 65)
+#define FE_SET_TONE _IO('o', 66)
+#define FE_SET_VOLTAGE _IO('o', 67)
+#define FE_ENABLE_HIGH_LNB_VOLTAGE _IO('o', 68)
+#define FE_READ_STATUS _IOR('o', 69, fe_status_t)
+#define FE_READ_BER _IOR('o', 70, __u32)
+#define FE_READ_SIGNAL_STRENGTH _IOR('o', 71, __u16)
+#define FE_READ_SNR _IOR('o', 72, __u16)
+#define FE_READ_UNCORRECTED_BLOCKS _IOR('o', 73, __u32)
+#define FE_SET_FRONTEND_TUNE_MODE _IO('o', 81)
+#define FE_GET_EVENT _IOR('o', 78, struct dvb_frontend_event)
+#define FE_DISHNETWORK_SEND_LEGACY_CMD _IO('o', 80)
+#define FE_SET_PROPERTY _IOW('o', 82, struct dtv_properties)
+#define FE_GET_PROPERTY _IOR('o', 83, struct dtv_properties)
 enum fe_bandwidth {
   BANDWIDTH_8_MHZ,
   BANDWIDTH_7_MHZ,
@@ -413,25 +426,6 @@
   fe_status_t status;
   struct dvb_frontend_parameters parameters;
 };
-#define FE_SET_PROPERTY _IOW('o', 82, struct dtv_properties)
-#define FE_GET_PROPERTY _IOR('o', 83, struct dtv_properties)
-#define FE_TUNE_MODE_ONESHOT 0x01
-#define FE_GET_INFO _IOR('o', 61, struct dvb_frontend_info)
-#define FE_DISEQC_RESET_OVERLOAD _IO('o', 62)
-#define FE_DISEQC_SEND_MASTER_CMD _IOW('o', 63, struct dvb_diseqc_master_cmd)
-#define FE_DISEQC_RECV_SLAVE_REPLY _IOR('o', 64, struct dvb_diseqc_slave_reply)
-#define FE_DISEQC_SEND_BURST _IO('o', 65)
-#define FE_SET_TONE _IO('o', 66)
-#define FE_SET_VOLTAGE _IO('o', 67)
-#define FE_ENABLE_HIGH_LNB_VOLTAGE _IO('o', 68)
-#define FE_READ_STATUS _IOR('o', 69, fe_status_t)
-#define FE_READ_BER _IOR('o', 70, __u32)
-#define FE_READ_SIGNAL_STRENGTH _IOR('o', 71, __u16)
-#define FE_READ_SNR _IOR('o', 72, __u16)
-#define FE_READ_UNCORRECTED_BLOCKS _IOR('o', 73, __u32)
 #define FE_SET_FRONTEND _IOW('o', 76, struct dvb_frontend_parameters)
 #define FE_GET_FRONTEND _IOR('o', 77, struct dvb_frontend_parameters)
-#define FE_SET_FRONTEND_TUNE_MODE _IO('o', 81)
-#define FE_GET_EVENT _IOR('o', 78, struct dvb_frontend_event)
-#define FE_DISHNETWORK_SEND_LEGACY_CMD _IO('o', 80)
 #endif
diff --git a/libc/kernel/uapi/linux/dvb/video.h b/libc/kernel/uapi/linux/dvb/video.h
index e235114..7ada1a0 100644
--- a/libc/kernel/uapi/linux/dvb/video.h
+++ b/libc/kernel/uapi/linux/dvb/video.h
@@ -89,7 +89,7 @@
 #define VIDEO_EVENT_FRAME_RATE_CHANGED 2
 #define VIDEO_EVENT_DECODER_STOPPED 3
 #define VIDEO_EVENT_VSYNC 4
-  __kernel_time_t timestamp;
+  long timestamp;
   union {
     video_size_t size;
     unsigned int frame_rate;
diff --git a/libc/kernel/uapi/linux/errqueue.h b/libc/kernel/uapi/linux/errqueue.h
index 5daeb10..196189b 100644
--- a/libc/kernel/uapi/linux/errqueue.h
+++ b/libc/kernel/uapi/linux/errqueue.h
@@ -33,8 +33,10 @@
 #define SO_EE_ORIGIN_ICMP 2
 #define SO_EE_ORIGIN_ICMP6 3
 #define SO_EE_ORIGIN_TXSTATUS 4
+#define SO_EE_ORIGIN_ZEROCOPY 5
 #define SO_EE_ORIGIN_TIMESTAMPING SO_EE_ORIGIN_TXSTATUS
 #define SO_EE_OFFENDER(ee) ((struct sockaddr *) ((ee) + 1))
+#define SO_EE_CODE_ZEROCOPY_COPIED 1
 struct scm_timestamping {
   struct timespec ts[3];
 };
diff --git a/libc/kernel/uapi/linux/ethtool.h b/libc/kernel/uapi/linux/ethtool.h
index 56df94b..6f1c0f3 100644
--- a/libc/kernel/uapi/linux/ethtool.h
+++ b/libc/kernel/uapi/linux/ethtool.h
@@ -418,6 +418,24 @@
   __u32 queue_mask[__KERNEL_DIV_ROUND_UP(MAX_NUM_QUEUE, 32)];
   char data[];
 };
+struct ethtool_fecparam {
+  __u32 cmd;
+  __u32 active_fec;
+  __u32 fec;
+  __u32 reserved;
+};
+enum ethtool_fec_config_bits {
+  ETHTOOL_FEC_NONE_BIT,
+  ETHTOOL_FEC_AUTO_BIT,
+  ETHTOOL_FEC_OFF_BIT,
+  ETHTOOL_FEC_RS_BIT,
+  ETHTOOL_FEC_BASER_BIT,
+};
+#define ETHTOOL_FEC_NONE (1 << ETHTOOL_FEC_NONE_BIT)
+#define ETHTOOL_FEC_AUTO (1 << ETHTOOL_FEC_AUTO_BIT)
+#define ETHTOOL_FEC_OFF (1 << ETHTOOL_FEC_OFF_BIT)
+#define ETHTOOL_FEC_RS (1 << ETHTOOL_FEC_RS_BIT)
+#define ETHTOOL_FEC_BASER (1 << ETHTOOL_FEC_BASER_BIT)
 #define ETHTOOL_GSET 0x00000001
 #define ETHTOOL_SSET 0x00000002
 #define ETHTOOL_GDRVINFO 0x00000003
@@ -496,6 +514,8 @@
 #define ETHTOOL_SLINKSETTINGS 0x0000004d
 #define ETHTOOL_PHY_GTUNABLE 0x0000004e
 #define ETHTOOL_PHY_STUNABLE 0x0000004f
+#define ETHTOOL_GFECPARAM 0x00000050
+#define ETHTOOL_SFECPARAM 0x00000051
 #define SPARC_ETH_GSET ETHTOOL_GSET
 #define SPARC_ETH_SSET ETHTOOL_SSET
 enum ethtool_link_mode_bit_indices {
@@ -548,7 +568,10 @@
   ETHTOOL_LINK_MODE_10000baseER_Full_BIT = 46,
   ETHTOOL_LINK_MODE_2500baseT_Full_BIT = 47,
   ETHTOOL_LINK_MODE_5000baseT_Full_BIT = 48,
-  __ETHTOOL_LINK_MODE_LAST = ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
+  ETHTOOL_LINK_MODE_FEC_NONE_BIT = 49,
+  ETHTOOL_LINK_MODE_FEC_RS_BIT = 50,
+  ETHTOOL_LINK_MODE_FEC_BASER_BIT = 51,
+  __ETHTOOL_LINK_MODE_LAST = ETHTOOL_LINK_MODE_FEC_BASER_BIT,
 };
 #define __ETHTOOL_LINK_MODE_LEGACY_MASK(base_name) (1UL << (ETHTOOL_LINK_MODE_ ##base_name ##_BIT))
 #define SUPPORTED_10baseT_Half __ETHTOOL_LINK_MODE_LEGACY_MASK(10baseT_Half)
@@ -721,7 +744,9 @@
   __u8 eth_tp_mdix;
   __u8 eth_tp_mdix_ctrl;
   __s8 link_mode_masks_nwords;
-  __u32 reserved[8];
+  __u8 transceiver;
+  __u8 reserved1[3];
+  __u32 reserved[7];
   __u32 link_mode_masks[0];
 };
 #endif
diff --git a/libc/kernel/uapi/linux/fcntl.h b/libc/kernel/uapi/linux/fcntl.h
index c4a8314..e98a67b 100644
--- a/libc/kernel/uapi/linux/fcntl.h
+++ b/libc/kernel/uapi/linux/fcntl.h
@@ -32,6 +32,16 @@
 #define F_SEAL_SHRINK 0x0002
 #define F_SEAL_GROW 0x0004
 #define F_SEAL_WRITE 0x0008
+#define F_GET_RW_HINT (F_LINUX_SPECIFIC_BASE + 11)
+#define F_SET_RW_HINT (F_LINUX_SPECIFIC_BASE + 12)
+#define F_GET_FILE_RW_HINT (F_LINUX_SPECIFIC_BASE + 13)
+#define F_SET_FILE_RW_HINT (F_LINUX_SPECIFIC_BASE + 14)
+#define RWF_WRITE_LIFE_NOT_SET 0
+#define RWH_WRITE_LIFE_NONE 1
+#define RWH_WRITE_LIFE_SHORT 2
+#define RWH_WRITE_LIFE_MEDIUM 3
+#define RWH_WRITE_LIFE_LONG 4
+#define RWH_WRITE_LIFE_EXTREME 5
 #define DN_ACCESS 0x00000001
 #define DN_MODIFY 0x00000002
 #define DN_CREATE 0x00000004
diff --git a/libc/kernel/uapi/linux/fs.h b/libc/kernel/uapi/linux/fs.h
index 75c17a4..f4e74cd 100644
--- a/libc/kernel/uapi/linux/fs.h
+++ b/libc/kernel/uapi/linux/fs.h
@@ -193,6 +193,8 @@
 #define FS_ENCRYPTION_MODE_AES_256_GCM 2
 #define FS_ENCRYPTION_MODE_AES_256_CBC 3
 #define FS_ENCRYPTION_MODE_AES_256_CTS 4
+#define FS_ENCRYPTION_MODE_AES_128_CBC 5
+#define FS_ENCRYPTION_MODE_AES_128_CTS 6
 struct fscrypt_policy {
   __u8 version;
   __u8 contents_encryption_mode;
@@ -243,7 +245,10 @@
 #define SYNC_FILE_RANGE_WAIT_BEFORE 1
 #define SYNC_FILE_RANGE_WRITE 2
 #define SYNC_FILE_RANGE_WAIT_AFTER 4
-#define RWF_HIPRI 0x00000001
-#define RWF_DSYNC 0x00000002
-#define RWF_SYNC 0x00000004
+typedef int __bitwise __kernel_rwf_t;
+#define RWF_HIPRI ((__force __kernel_rwf_t) 0x00000001)
+#define RWF_DSYNC ((__force __kernel_rwf_t) 0x00000002)
+#define RWF_SYNC ((__force __kernel_rwf_t) 0x00000004)
+#define RWF_NOWAIT ((__force __kernel_rwf_t) 0x00000008)
+#define RWF_SUPPORTED (RWF_HIPRI | RWF_DSYNC | RWF_SYNC | RWF_NOWAIT)
 #endif
diff --git a/libc/kernel/uapi/linux/if_arp.h b/libc/kernel/uapi/linux/if_arp.h
index 9f056fb..0b1959d 100644
--- a/libc/kernel/uapi/linux/if_arp.h
+++ b/libc/kernel/uapi/linux/if_arp.h
@@ -50,6 +50,7 @@
 #define ARPHRD_LAPB 516
 #define ARPHRD_DDCMP 517
 #define ARPHRD_RAWHDLC 518
+#define ARPHRD_RAWIP 519
 #define ARPHRD_TUNNEL 768
 #define ARPHRD_TUNNEL6 769
 #define ARPHRD_FRAD 770
diff --git a/libc/kernel/uapi/linux/if_ether.h b/libc/kernel/uapi/linux/if_ether.h
index 846d238..f40321e 100644
--- a/libc/kernel/uapi/linux/if_ether.h
+++ b/libc/kernel/uapi/linux/if_ether.h
@@ -51,6 +51,7 @@
 #define ETH_P_ATALK 0x809B
 #define ETH_P_AARP 0x80F3
 #define ETH_P_8021Q 0x8100
+#define ETH_P_ERSPAN 0x88BE
 #define ETH_P_IPX 0x8137
 #define ETH_P_IPV6 0x86DD
 #define ETH_P_PAUSE 0x8808
@@ -80,11 +81,13 @@
 #define ETH_P_FIP 0x8914
 #define ETH_P_80221 0x8917
 #define ETH_P_HSR 0x892F
+#define ETH_P_NSH 0x894F
 #define ETH_P_LOOPBACK 0x9000
 #define ETH_P_QINQ1 0x9100
 #define ETH_P_QINQ2 0x9200
 #define ETH_P_QINQ3 0x9300
 #define ETH_P_EDSA 0xDADA
+#define ETH_P_IFE 0xED3E
 #define ETH_P_AF_IUCV 0xFBFB
 #define ETH_P_802_3_MIN 0x0600
 #define ETH_P_802_3 0x0001
@@ -112,6 +115,7 @@
 #define ETH_P_IEEE802154 0x00F6
 #define ETH_P_CAIF 0x00F7
 #define ETH_P_XDSA 0x00F8
+#define ETH_P_MAP 0x00F9
 struct ethhdr {
   unsigned char h_dest[ETH_ALEN];
   unsigned char h_source[ETH_ALEN];
diff --git a/libc/kernel/uapi/linux/if_link.h b/libc/kernel/uapi/linux/if_link.h
index 8ea790b..c041c82 100644
--- a/libc/kernel/uapi/linux/if_link.h
+++ b/libc/kernel/uapi/linux/if_link.h
@@ -135,6 +135,7 @@
   IFLA_GSO_MAX_SIZE,
   IFLA_PAD,
   IFLA_XDP,
+  IFLA_EVENT,
   __IFLA_MAX
 };
 #define IFLA_MAX (__IFLA_MAX - 1)
@@ -693,18 +694,31 @@
 #define XDP_FLAGS_UPDATE_IF_NOEXIST (1U << 0)
 #define XDP_FLAGS_SKB_MODE (1U << 1)
 #define XDP_FLAGS_DRV_MODE (1U << 2)
-#define XDP_FLAGS_MASK (XDP_FLAGS_UPDATE_IF_NOEXIST | XDP_FLAGS_SKB_MODE | XDP_FLAGS_DRV_MODE)
+#define XDP_FLAGS_HW_MODE (1U << 3)
+#define XDP_FLAGS_MODES (XDP_FLAGS_SKB_MODE | XDP_FLAGS_DRV_MODE | XDP_FLAGS_HW_MODE)
+#define XDP_FLAGS_MASK (XDP_FLAGS_UPDATE_IF_NOEXIST | XDP_FLAGS_MODES)
 enum {
   XDP_ATTACHED_NONE = 0,
   XDP_ATTACHED_DRV,
   XDP_ATTACHED_SKB,
+  XDP_ATTACHED_HW,
 };
 enum {
   IFLA_XDP_UNSPEC,
   IFLA_XDP_FD,
   IFLA_XDP_ATTACHED,
   IFLA_XDP_FLAGS,
+  IFLA_XDP_PROG_ID,
   __IFLA_XDP_MAX,
 };
 #define IFLA_XDP_MAX (__IFLA_XDP_MAX - 1)
+enum {
+  IFLA_EVENT_NONE,
+  IFLA_EVENT_REBOOT,
+  IFLA_EVENT_FEATURES,
+  IFLA_EVENT_BONDING_FAILOVER,
+  IFLA_EVENT_NOTIFY_PEERS,
+  IFLA_EVENT_IGMP_RESEND,
+  IFLA_EVENT_BONDING_OPTIONS,
+};
 #endif
diff --git a/libc/kernel/uapi/linux/if_tunnel.h b/libc/kernel/uapi/linux/if_tunnel.h
index aaad4cb..bfc6479 100644
--- a/libc/kernel/uapi/linux/if_tunnel.h
+++ b/libc/kernel/uapi/linux/if_tunnel.h
@@ -134,6 +134,7 @@
   IFLA_GRE_COLLECT_METADATA,
   IFLA_GRE_IGNORE_DF,
   IFLA_GRE_FWMARK,
+  IFLA_GRE_ERSPAN_INDEX,
   __IFLA_GRE_MAX,
 };
 #define IFLA_GRE_MAX (__IFLA_GRE_MAX - 1)
diff --git a/libc/kernel/uapi/linux/inet_diag.h b/libc/kernel/uapi/linux/inet_diag.h
index 9753de0..47a3b34 100644
--- a/libc/kernel/uapi/linux/inet_diag.h
+++ b/libc/kernel/uapi/linux/inet_diag.h
@@ -119,6 +119,8 @@
   INET_DIAG_PAD,
   INET_DIAG_MARK,
   INET_DIAG_BBRINFO,
+  INET_DIAG_CLASS_ID,
+  INET_DIAG_MD5SIG,
   __INET_DIAG_MAX,
 };
 #define INET_DIAG_MAX (__INET_DIAG_MAX - 1)
diff --git a/libc/kernel/uapi/linux/input-event-codes.h b/libc/kernel/uapi/linux/input-event-codes.h
index aea69f3..346ec91 100644
--- a/libc/kernel/uapi/linux/input-event-codes.h
+++ b/libc/kernel/uapi/linux/input-event-codes.h
@@ -538,6 +538,7 @@
 #define KEY_APPSELECT 0x244
 #define KEY_SCREENSAVER 0x245
 #define KEY_VOICECOMMAND 0x246
+#define KEY_ASSISTANT 0x247
 #define KEY_BRIGHTNESS_MIN 0x250
 #define KEY_BRIGHTNESS_MAX 0x251
 #define KEY_KBDINPUTASSIST_PREV 0x260
diff --git a/libc/kernel/uapi/linux/kcmp.h b/libc/kernel/uapi/linux/kcmp.h
index 53064b1..d185c0a 100644
--- a/libc/kernel/uapi/linux/kcmp.h
+++ b/libc/kernel/uapi/linux/kcmp.h
@@ -18,6 +18,7 @@
  ****************************************************************************/
 #ifndef _UAPI_LINUX_KCMP_H
 #define _UAPI_LINUX_KCMP_H
+#include <linux/types.h>
 enum kcmp_type {
   KCMP_FILE,
   KCMP_VM,
@@ -26,6 +27,12 @@
   KCMP_SIGHAND,
   KCMP_IO,
   KCMP_SYSVSEM,
+  KCMP_EPOLL_TFD,
   KCMP_TYPES,
 };
+struct kcmp_epoll_slot {
+  __u32 efd;
+  __u32 tfd;
+  __u32 toff;
+};
 #endif
diff --git a/libc/kernel/uapi/linux/kfd_ioctl.h b/libc/kernel/uapi/linux/kfd_ioctl.h
index 79e5c01..f870cd6 100644
--- a/libc/kernel/uapi/linux/kfd_ioctl.h
+++ b/libc/kernel/uapi/linux/kfd_ioctl.h
@@ -18,13 +18,13 @@
  ****************************************************************************/
 #ifndef KFD_IOCTL_H_INCLUDED
 #define KFD_IOCTL_H_INCLUDED
-#include <linux/types.h>
+#include <drm/drm.h>
 #include <linux/ioctl.h>
 #define KFD_IOCTL_MAJOR_VERSION 1
 #define KFD_IOCTL_MINOR_VERSION 1
 struct kfd_ioctl_get_version_args {
-  uint32_t major_version;
-  uint32_t minor_version;
+  __u32 major_version;
+  __u32 minor_version;
 };
 #define KFD_IOC_QUEUE_TYPE_COMPUTE 0
 #define KFD_IOC_QUEUE_TYPE_SDMA 1
@@ -32,86 +32,86 @@
 #define KFD_MAX_QUEUE_PERCENTAGE 100
 #define KFD_MAX_QUEUE_PRIORITY 15
 struct kfd_ioctl_create_queue_args {
-  uint64_t ring_base_address;
-  uint64_t write_pointer_address;
-  uint64_t read_pointer_address;
-  uint64_t doorbell_offset;
-  uint32_t ring_size;
-  uint32_t gpu_id;
-  uint32_t queue_type;
-  uint32_t queue_percentage;
-  uint32_t queue_priority;
-  uint32_t queue_id;
-  uint64_t eop_buffer_address;
-  uint64_t eop_buffer_size;
-  uint64_t ctx_save_restore_address;
-  uint64_t ctx_save_restore_size;
+  __u64 ring_base_address;
+  __u64 write_pointer_address;
+  __u64 read_pointer_address;
+  __u64 doorbell_offset;
+  __u32 ring_size;
+  __u32 gpu_id;
+  __u32 queue_type;
+  __u32 queue_percentage;
+  __u32 queue_priority;
+  __u32 queue_id;
+  __u64 eop_buffer_address;
+  __u64 eop_buffer_size;
+  __u64 ctx_save_restore_address;
+  __u64 ctx_save_restore_size;
 };
 struct kfd_ioctl_destroy_queue_args {
-  uint32_t queue_id;
-  uint32_t pad;
+  __u32 queue_id;
+  __u32 pad;
 };
 struct kfd_ioctl_update_queue_args {
-  uint64_t ring_base_address;
-  uint32_t queue_id;
-  uint32_t ring_size;
-  uint32_t queue_percentage;
-  uint32_t queue_priority;
+  __u64 ring_base_address;
+  __u32 queue_id;
+  __u32 ring_size;
+  __u32 queue_percentage;
+  __u32 queue_priority;
 };
 #define KFD_IOC_CACHE_POLICY_COHERENT 0
 #define KFD_IOC_CACHE_POLICY_NONCOHERENT 1
 struct kfd_ioctl_set_memory_policy_args {
-  uint64_t alternate_aperture_base;
-  uint64_t alternate_aperture_size;
-  uint32_t gpu_id;
-  uint32_t default_policy;
-  uint32_t alternate_policy;
-  uint32_t pad;
+  __u64 alternate_aperture_base;
+  __u64 alternate_aperture_size;
+  __u32 gpu_id;
+  __u32 default_policy;
+  __u32 alternate_policy;
+  __u32 pad;
 };
 struct kfd_ioctl_get_clock_counters_args {
-  uint64_t gpu_clock_counter;
-  uint64_t cpu_clock_counter;
-  uint64_t system_clock_counter;
-  uint64_t system_clock_freq;
-  uint32_t gpu_id;
-  uint32_t pad;
+  __u64 gpu_clock_counter;
+  __u64 cpu_clock_counter;
+  __u64 system_clock_counter;
+  __u64 system_clock_freq;
+  __u32 gpu_id;
+  __u32 pad;
 };
 #define NUM_OF_SUPPORTED_GPUS 7
 struct kfd_process_device_apertures {
-  uint64_t lds_base;
-  uint64_t lds_limit;
-  uint64_t scratch_base;
-  uint64_t scratch_limit;
-  uint64_t gpuvm_base;
-  uint64_t gpuvm_limit;
-  uint32_t gpu_id;
-  uint32_t pad;
+  __u64 lds_base;
+  __u64 lds_limit;
+  __u64 scratch_base;
+  __u64 scratch_limit;
+  __u64 gpuvm_base;
+  __u64 gpuvm_limit;
+  __u32 gpu_id;
+  __u32 pad;
 };
 struct kfd_ioctl_get_process_apertures_args {
   struct kfd_process_device_apertures process_apertures[NUM_OF_SUPPORTED_GPUS];
-  uint32_t num_of_nodes;
-  uint32_t pad;
+  __u32 num_of_nodes;
+  __u32 pad;
 };
 #define MAX_ALLOWED_NUM_POINTS 100
 #define MAX_ALLOWED_AW_BUFF_SIZE 4096
 #define MAX_ALLOWED_WAC_BUFF_SIZE 128
 struct kfd_ioctl_dbg_register_args {
-  uint32_t gpu_id;
-  uint32_t pad;
+  __u32 gpu_id;
+  __u32 pad;
 };
 struct kfd_ioctl_dbg_unregister_args {
-  uint32_t gpu_id;
-  uint32_t pad;
+  __u32 gpu_id;
+  __u32 pad;
 };
 struct kfd_ioctl_dbg_address_watch_args {
-  uint64_t content_ptr;
-  uint32_t gpu_id;
-  uint32_t buf_size_in_bytes;
+  __u64 content_ptr;
+  __u32 gpu_id;
+  __u32 buf_size_in_bytes;
 };
 struct kfd_ioctl_dbg_wave_control_args {
-  uint64_t content_ptr;
-  uint32_t gpu_id;
-  uint32_t buf_size_in_bytes;
+  __u64 content_ptr;
+  __u32 gpu_id;
+  __u32 buf_size_in_bytes;
 };
 #define KFD_IOC_EVENT_SIGNAL 0
 #define KFD_IOC_EVENT_NODECHANGE 1
@@ -127,52 +127,67 @@
 #define KFD_IOC_WAIT_RESULT_FAIL 2
 #define KFD_SIGNAL_EVENT_LIMIT 256
 struct kfd_ioctl_create_event_args {
-  uint64_t event_page_offset;
-  uint32_t event_trigger_data;
-  uint32_t event_type;
-  uint32_t auto_reset;
-  uint32_t node_id;
-  uint32_t event_id;
-  uint32_t event_slot_index;
+  __u64 event_page_offset;
+  __u32 event_trigger_data;
+  __u32 event_type;
+  __u32 auto_reset;
+  __u32 node_id;
+  __u32 event_id;
+  __u32 event_slot_index;
 };
 struct kfd_ioctl_destroy_event_args {
-  uint32_t event_id;
-  uint32_t pad;
+  __u32 event_id;
+  __u32 pad;
 };
 struct kfd_ioctl_set_event_args {
-  uint32_t event_id;
-  uint32_t pad;
+  __u32 event_id;
+  __u32 pad;
 };
 struct kfd_ioctl_reset_event_args {
-  uint32_t event_id;
-  uint32_t pad;
+  __u32 event_id;
+  __u32 pad;
 };
 struct kfd_memory_exception_failure {
-  uint32_t NotPresent;
-  uint32_t ReadOnly;
-  uint32_t NoExecute;
-  uint32_t pad;
+  __u32 NotPresent;
+  __u32 ReadOnly;
+  __u32 NoExecute;
+  __u32 pad;
 };
 struct kfd_hsa_memory_exception_data {
   struct kfd_memory_exception_failure failure;
-  uint64_t va;
-  uint32_t gpu_id;
-  uint32_t pad;
+  __u64 va;
+  __u32 gpu_id;
+  __u32 pad;
 };
 struct kfd_event_data {
   union {
     struct kfd_hsa_memory_exception_data memory_exception_data;
   };
-  uint64_t kfd_event_data_ext;
-  uint32_t event_id;
-  uint32_t pad;
+  __u64 kfd_event_data_ext;
+  __u32 event_id;
+  __u32 pad;
 };
 struct kfd_ioctl_wait_events_args {
-  uint64_t events_ptr;
-  uint32_t num_events;
-  uint32_t wait_for_all;
-  uint32_t timeout;
-  uint32_t wait_result;
+  __u64 events_ptr;
+  __u32 num_events;
+  __u32 wait_for_all;
+  __u32 timeout;
+  __u32 wait_result;
+};
+struct kfd_ioctl_set_scratch_backing_va_args {
+  uint64_t va_addr;
+  uint32_t gpu_id;
+  uint32_t pad;
+};
+struct kfd_ioctl_get_tile_config_args {
+  uint64_t tile_config_ptr;
+  uint64_t macro_tile_config_ptr;
+  uint32_t num_tile_configs;
+  uint32_t num_macro_tile_configs;
+  uint32_t gpu_id;
+  uint32_t gb_addr_config;
+  uint32_t num_banks;
+  uint32_t num_ranks;
 };
 #define AMDKFD_IOCTL_BASE 'K'
 #define AMDKFD_IO(nr) _IO(AMDKFD_IOCTL_BASE, nr)
@@ -195,6 +210,8 @@
 #define AMDKFD_IOC_DBG_UNREGISTER AMDKFD_IOW(0x0E, struct kfd_ioctl_dbg_unregister_args)
 #define AMDKFD_IOC_DBG_ADDRESS_WATCH AMDKFD_IOW(0x0F, struct kfd_ioctl_dbg_address_watch_args)
 #define AMDKFD_IOC_DBG_WAVE_CONTROL AMDKFD_IOW(0x10, struct kfd_ioctl_dbg_wave_control_args)
+#define AMDKFD_IOC_SET_SCRATCH_BACKING_VA AMDKFD_IOWR(0x11, struct kfd_ioctl_set_scratch_backing_va_args)
+#define AMDKFD_IOC_GET_TILE_CONFIG AMDKFD_IOWR(0x12, struct kfd_ioctl_get_tile_config_args)
 #define AMDKFD_COMMAND_START 0x01
-#define AMDKFD_COMMAND_END 0x11
+#define AMDKFD_COMMAND_END 0x13
 #endif
diff --git a/libc/kernel/uapi/linux/kvm.h b/libc/kernel/uapi/linux/kvm.h
index f61a08b..6bd4701 100644
--- a/libc/kernel/uapi/linux/kvm.h
+++ b/libc/kernel/uapi/linux/kvm.h
@@ -123,6 +123,17 @@
   __u32 flags;
   __u32 reserved[9];
 };
+#define KVM_S390_CMMA_PEEK (1 << 0)
+struct kvm_s390_cmma_log {
+  __u64 start_gfn;
+  __u32 count;
+  __u32 flags;
+  union {
+    __u64 remaining;
+    __u64 mask;
+  };
+  __u64 values;
+};
 struct kvm_hyperv_exit {
 #define KVM_EXIT_HYPERV_SYNIC 1
 #define KVM_EXIT_HYPERV_HCALL 2
@@ -526,7 +537,8 @@
 struct kvm_ppc_smmu_info {
   __u64 flags;
   __u32 slb_size;
-  __u32 pad;
+  __u16 data_keys;
+  __u16 instr_keys;
   struct kvm_ppc_one_seg_page_size sps[KVM_PPC_PAGE_SIZES_MAX_SZ];
 };
 struct kvm_ppc_resize_hpt {
@@ -711,6 +723,11 @@
 #define KVM_CAP_SPAPR_TCE_VFIO 142
 #define KVM_CAP_X86_GUEST_MWAIT 143
 #define KVM_CAP_ARM_USER_IRQ 144
+#define KVM_CAP_S390_CMMA_MIGRATION 145
+#define KVM_CAP_PPC_FWNMI 146
+#define KVM_CAP_PPC_SMT_POSSIBLE 147
+#define KVM_CAP_HYPERV_SYNIC2 148
+#define KVM_CAP_HYPERV_VP_INDEX 149
 #ifdef KVM_CAP_IRQ_ROUTING
 struct kvm_irq_routing_irqchip {
   __u32 irqchip;
@@ -1009,6 +1026,8 @@
 #define KVM_S390_SET_IRQ_STATE _IOW(KVMIO, 0xb5, struct kvm_s390_irq_state)
 #define KVM_S390_GET_IRQ_STATE _IOW(KVMIO, 0xb6, struct kvm_s390_irq_state)
 #define KVM_SMI _IO(KVMIO, 0xb7)
+#define KVM_S390_GET_CMMA_BITS _IOWR(KVMIO, 0xb8, struct kvm_s390_cmma_log)
+#define KVM_S390_SET_CMMA_BITS _IOW(KVMIO, 0xb9, struct kvm_s390_cmma_log)
 #define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0)
 #define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1)
 #define KVM_DEV_ASSIGN_MASK_INTX (1 << 2)
diff --git a/libc/kernel/uapi/linux/limits.h b/libc/kernel/uapi/linux/limits.h
index 41108f9..ad0e33e 100644
--- a/libc/kernel/uapi/linux/limits.h
+++ b/libc/kernel/uapi/linux/limits.h
@@ -20,7 +20,7 @@
 #define _LINUX_LIMITS_H
 #define NR_OPEN 1024
 #define NGROUPS_MAX 65536
-#define _KERNEL_ARG_MAX 131072
+#define ARG_MAX 131072
 #define LINK_MAX 127
 #define MAX_CANON 255
 #define MAX_INPUT 255
diff --git a/libc/kernel/uapi/linux/loop.h b/libc/kernel/uapi/linux/loop.h
index ff3482f..d5a23b5 100644
--- a/libc/kernel/uapi/linux/loop.h
+++ b/libc/kernel/uapi/linux/loop.h
@@ -77,6 +77,7 @@
 #define LOOP_CHANGE_FD 0x4C06
 #define LOOP_SET_CAPACITY 0x4C07
 #define LOOP_SET_DIRECT_IO 0x4C08
+#define LOOP_SET_BLOCK_SIZE 0x4C09
 #define LOOP_CTL_ADD 0x4C80
 #define LOOP_CTL_REMOVE 0x4C81
 #define LOOP_CTL_GET_FREE 0x4C82
diff --git a/libc/kernel/uapi/linux/lwtunnel.h b/libc/kernel/uapi/linux/lwtunnel.h
index c88d866..05cc4fd 100644
--- a/libc/kernel/uapi/linux/lwtunnel.h
+++ b/libc/kernel/uapi/linux/lwtunnel.h
@@ -27,6 +27,7 @@
   LWTUNNEL_ENCAP_IP6,
   LWTUNNEL_ENCAP_SEG6,
   LWTUNNEL_ENCAP_BPF,
+  LWTUNNEL_ENCAP_SEG6_LOCAL,
   __LWTUNNEL_ENCAP_MAX,
 };
 #define LWTUNNEL_ENCAP_MAX (__LWTUNNEL_ENCAP_MAX - 1)
diff --git a/libc/kernel/uapi/linux/magic.h b/libc/kernel/uapi/linux/magic.h
index a9dac5d..6e0ddf7 100644
--- a/libc/kernel/uapi/linux/magic.h
+++ b/libc/kernel/uapi/linux/magic.h
@@ -57,6 +57,7 @@
 #define MSDOS_SUPER_MAGIC 0x4d44
 #define NCP_SUPER_MAGIC 0x564c
 #define NFS_SUPER_MAGIC 0x6969
+#define OCFS2_SUPER_MAGIC 0x7461636f
 #define OPENPROM_SUPER_MAGIC 0x9fa1
 #define QNX4_SUPER_MAGIC 0x002f
 #define QNX6_SUPER_MAGIC 0x68191122
@@ -86,6 +87,7 @@
 #define BTRFS_TEST_MAGIC 0x73727279
 #define NSFS_MAGIC 0x6e736673
 #define BPF_FS_MAGIC 0xcafe4a11
+#define AAFS_MAGIC 0x5a3c69f0
 #define UDF_SUPER_MAGIC 0x15013346
 #define BALLOON_KVM_MAGIC 0x13661366
 #define ZSMALLOC_MAGIC 0x58295829
diff --git a/libc/kernel/uapi/linux/wil6210_uapi.h b/libc/kernel/uapi/linux/max2175.h
similarity index 62%
copy from libc/kernel/uapi/linux/wil6210_uapi.h
copy to libc/kernel/uapi/linux/max2175.h
index e68b6c8..e6998e1 100644
--- a/libc/kernel/uapi/linux/wil6210_uapi.h
+++ b/libc/kernel/uapi/linux/max2175.h
@@ -16,30 +16,10 @@
  ***
  ****************************************************************************
  ****************************************************************************/
-#ifndef __WIL6210_UAPI_H__
-#define __WIL6210_UAPI_H__
-#define __user
-#include <linux/sockios.h>
-#define WIL_IOCTL_MEMIO (SIOCDEVPRIVATE + 2)
-#define WIL_IOCTL_MEMIO_BLOCK (SIOCDEVPRIVATE + 3)
-enum wil_memio_op {
-  wil_mmio_read = 0,
-  wil_mmio_write = 1,
-  wil_mmio_op_mask = 0xff,
-  wil_mmio_addr_linker = 0 << 8,
-  wil_mmio_addr_ahb = 1 << 8,
-  wil_mmio_addr_bar = 2 << 8,
-  wil_mmio_addr_mask = 0xff00,
-};
-struct wil_memio {
-  uint32_t op;
-  uint32_t addr;
-  uint32_t val;
-};
-struct wil_memio_block {
-  uint32_t op;
-  uint32_t addr;
-  uint32_t size;
-  void __user * block;
-};
+#ifndef __UAPI_MAX2175_H_
+#define __UAPI_MAX2175_H_
+#include <linux/v4l2-controls.h>
+#define V4L2_CID_MAX2175_I2S_ENABLE (V4L2_CID_USER_MAX217X_BASE + 0x01)
+#define V4L2_CID_MAX2175_HSLS (V4L2_CID_USER_MAX217X_BASE + 0x02)
+#define V4L2_CID_MAX2175_RX_MODE (V4L2_CID_USER_MAX217X_BASE + 0x03)
 #endif
diff --git a/libc/kernel/uapi/linux/media.h b/libc/kernel/uapi/linux/media.h
index 690d9b2a..b24d616 100644
--- a/libc/kernel/uapi/linux/media.h
+++ b/libc/kernel/uapi/linux/media.h
@@ -22,7 +22,6 @@
 #include <linux/ioctl.h>
 #include <linux/types.h>
 #include <linux/version.h>
-#define MEDIA_API_VERSION KERNEL_VERSION(0, 1, 0)
 struct media_device_info {
   char driver[16];
   char model[32];
@@ -56,6 +55,8 @@
 #define MEDIA_ENT_F_PROC_VIDEO_LUT (MEDIA_ENT_F_BASE + 0x4004)
 #define MEDIA_ENT_F_PROC_VIDEO_SCALER (MEDIA_ENT_F_BASE + 0x4005)
 #define MEDIA_ENT_F_PROC_VIDEO_STATISTICS (MEDIA_ENT_F_BASE + 0x4006)
+#define MEDIA_ENT_F_VID_MUX (MEDIA_ENT_F_BASE + 0x5001)
+#define MEDIA_ENT_F_VID_IF_BRIDGE (MEDIA_ENT_F_BASE + 0x5002)
 #define MEDIA_ENT_F_IO_V4L (MEDIA_ENT_F_OLD_BASE + 1)
 #define MEDIA_ENT_F_CAM_SENSOR (MEDIA_ENT_F_OLD_SUBDEV_BASE + 1)
 #define MEDIA_ENT_F_FLASH (MEDIA_ENT_F_OLD_SUBDEV_BASE + 2)
@@ -80,6 +81,7 @@
 #define MEDIA_ENT_T_V4L2_SUBDEV_LENS MEDIA_ENT_F_LENS
 #define MEDIA_ENT_T_V4L2_SUBDEV_DECODER MEDIA_ENT_F_ATV_DECODER
 #define MEDIA_ENT_T_V4L2_SUBDEV_TUNER MEDIA_ENT_F_TUNER
+#define MEDIA_API_VERSION KERNEL_VERSION(0, 1, 0)
 #define MEDIA_ENT_FL_DEFAULT (1 << 0)
 #define MEDIA_ENT_FL_CONNECTOR (1 << 1)
 struct media_entity_desc {
diff --git a/libc/kernel/uapi/linux/membarrier.h b/libc/kernel/uapi/linux/membarrier.h
index e9edbaa..2f5ea7d 100644
--- a/libc/kernel/uapi/linux/membarrier.h
+++ b/libc/kernel/uapi/linux/membarrier.h
@@ -21,5 +21,7 @@
 enum membarrier_cmd {
   MEMBARRIER_CMD_QUERY = 0,
   MEMBARRIER_CMD_SHARED = (1 << 0),
+  MEMBARRIER_CMD_PRIVATE_EXPEDITED = (1 << 3),
+  MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED = (1 << 4),
 };
 #endif
diff --git a/libc/kernel/uapi/linux/memfd.h b/libc/kernel/uapi/linux/memfd.h
index d3d08a1..e3e5cd5 100644
--- a/libc/kernel/uapi/linux/memfd.h
+++ b/libc/kernel/uapi/linux/memfd.h
@@ -18,6 +18,20 @@
  ****************************************************************************/
 #ifndef _UAPI_LINUX_MEMFD_H
 #define _UAPI_LINUX_MEMFD_H
+#include <asm-generic/hugetlb_encode.h>
 #define MFD_CLOEXEC 0x0001U
 #define MFD_ALLOW_SEALING 0x0002U
+#define MFD_HUGETLB 0x0004U
+#define MFD_HUGE_SHIFT HUGETLB_FLAG_ENCODE_SHIFT
+#define MFD_HUGE_MASK HUGETLB_FLAG_ENCODE_MASK
+#define MFD_HUGE_64KB HUGETLB_FLAG_ENCODE_64KB
+#define MFD_HUGE_512KB HUGETLB_FLAG_ENCODE_512KB
+#define MFD_HUGE_1MB HUGETLB_FLAG_ENCODE_1MB
+#define MFD_HUGE_2MB HUGETLB_FLAG_ENCODE_2MB
+#define MFD_HUGE_8MB HUGETLB_FLAG_ENCODE_8MB
+#define MFD_HUGE_16MB HUGETLB_FLAG_ENCODE_16MB
+#define MFD_HUGE_256MB HUGETLB_FLAG_ENCODE_256MB
+#define MFD_HUGE_1GB HUGETLB_FLAG_ENCODE_1GB
+#define MFD_HUGE_2GB HUGETLB_FLAG_ENCODE_2GB
+#define MFD_HUGE_16GB HUGETLB_FLAG_ENCODE_16GB
 #endif
diff --git a/libc/kernel/uapi/linux/mempolicy.h b/libc/kernel/uapi/linux/mempolicy.h
index 081f9d6..6f721f6 100644
--- a/libc/kernel/uapi/linux/mempolicy.h
+++ b/libc/kernel/uapi/linux/mempolicy.h
@@ -27,12 +27,6 @@
   MPOL_LOCAL,
   MPOL_MAX,
 };
-enum mpol_rebind_step {
-  MPOL_REBIND_ONCE,
-  MPOL_REBIND_STEP1,
-  MPOL_REBIND_STEP2,
-  MPOL_REBIND_NSTEP,
-};
 #define MPOL_F_STATIC_NODES (1 << 15)
 #define MPOL_F_RELATIVE_NODES (1 << 14)
 #define MPOL_MODE_FLAGS (MPOL_F_STATIC_NODES | MPOL_F_RELATIVE_NODES)
@@ -47,7 +41,6 @@
 #define MPOL_MF_VALID (MPOL_MF_STRICT | MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)
 #define MPOL_F_SHARED (1 << 0)
 #define MPOL_F_LOCAL (1 << 1)
-#define MPOL_F_REBINDING (1 << 2)
 #define MPOL_F_MOF (1 << 3)
 #define MPOL_F_MORON (1 << 4)
 #endif
diff --git a/libc/kernel/uapi/linux/mman.h b/libc/kernel/uapi/linux/mman.h
index c5b3130..b0ce77e 100644
--- a/libc/kernel/uapi/linux/mman.h
+++ b/libc/kernel/uapi/linux/mman.h
@@ -19,9 +19,22 @@
 #ifndef _UAPI_LINUX_MMAN_H
 #define _UAPI_LINUX_MMAN_H
 #include <asm/mman.h>
+#include <asm-generic/hugetlb_encode.h>
 #define MREMAP_MAYMOVE 1
 #define MREMAP_FIXED 2
 #define OVERCOMMIT_GUESS 0
 #define OVERCOMMIT_ALWAYS 1
 #define OVERCOMMIT_NEVER 2
+#define MAP_HUGE_SHIFT HUGETLB_FLAG_ENCODE_SHIFT
+#define MAP_HUGE_MASK HUGETLB_FLAG_ENCODE_MASK
+#define MAP_HUGE_64KB HUGETLB_FLAG_ENCODE_64KB
+#define MAP_HUGE_512KB HUGETLB_FLAG_ENCODE_512KB
+#define MAP_HUGE_1MB HUGETLB_FLAG_ENCODE_1MB
+#define MAP_HUGE_2MB HUGETLB_FLAG_ENCODE_2MB
+#define MAP_HUGE_8MB HUGETLB_FLAG_ENCODE_8MB
+#define MAP_HUGE_16MB HUGETLB_FLAG_ENCODE_16MB
+#define MAP_HUGE_256MB HUGETLB_FLAG_ENCODE_256MB
+#define MAP_HUGE_1GB HUGETLB_FLAG_ENCODE_1GB
+#define MAP_HUGE_2GB HUGETLB_FLAG_ENCODE_2GB
+#define MAP_HUGE_16GB HUGETLB_FLAG_ENCODE_16GB
 #endif
diff --git a/libc/kernel/uapi/linux/mroute.h b/libc/kernel/uapi/linux/mroute.h
index 9f4c937..d962f8b 100644
--- a/libc/kernel/uapi/linux/mroute.h
+++ b/libc/kernel/uapi/linux/mroute.h
@@ -95,6 +95,48 @@
   unsigned char unused3;
   struct in_addr im_src, im_dst;
 };
+enum {
+  IPMRA_TABLE_UNSPEC,
+  IPMRA_TABLE_ID,
+  IPMRA_TABLE_CACHE_RES_QUEUE_LEN,
+  IPMRA_TABLE_MROUTE_REG_VIF_NUM,
+  IPMRA_TABLE_MROUTE_DO_ASSERT,
+  IPMRA_TABLE_MROUTE_DO_PIM,
+  IPMRA_TABLE_VIFS,
+  __IPMRA_TABLE_MAX
+};
+#define IPMRA_TABLE_MAX (__IPMRA_TABLE_MAX - 1)
+enum {
+  IPMRA_VIF_UNSPEC,
+  IPMRA_VIF,
+  __IPMRA_VIF_MAX
+};
+#define IPMRA_VIF_MAX (__IPMRA_VIF_MAX - 1)
+enum {
+  IPMRA_VIFA_UNSPEC,
+  IPMRA_VIFA_IFINDEX,
+  IPMRA_VIFA_VIF_ID,
+  IPMRA_VIFA_FLAGS,
+  IPMRA_VIFA_BYTES_IN,
+  IPMRA_VIFA_BYTES_OUT,
+  IPMRA_VIFA_PACKETS_IN,
+  IPMRA_VIFA_PACKETS_OUT,
+  IPMRA_VIFA_LOCAL_ADDR,
+  IPMRA_VIFA_REMOTE_ADDR,
+  IPMRA_VIFA_PAD,
+  __IPMRA_VIFA_MAX
+};
+#define IPMRA_VIFA_MAX (__IPMRA_VIFA_MAX - 1)
+enum {
+  IPMRA_CREPORT_UNSPEC,
+  IPMRA_CREPORT_MSGTYPE,
+  IPMRA_CREPORT_VIF_ID,
+  IPMRA_CREPORT_SRC_ADDR,
+  IPMRA_CREPORT_DST_ADDR,
+  IPMRA_CREPORT_PKT,
+  __IPMRA_CREPORT_MAX
+};
+#define IPMRA_CREPORT_MAX (__IPMRA_CREPORT_MAX - 1)
 #define MFC_ASSERT_THRESH (3 * HZ)
 #define IGMPMSG_NOCACHE 1
 #define IGMPMSG_WRONGVIF 2
diff --git a/libc/kernel/uapi/linux/mroute6.h b/libc/kernel/uapi/linux/mroute6.h
index d9c86bf..ccb38d9 100644
--- a/libc/kernel/uapi/linux/mroute6.h
+++ b/libc/kernel/uapi/linux/mroute6.h
@@ -94,4 +94,14 @@
   __u32 im6_pad;
   struct in6_addr im6_src, im6_dst;
 };
+enum {
+  IP6MRA_CREPORT_UNSPEC,
+  IP6MRA_CREPORT_MSGTYPE,
+  IP6MRA_CREPORT_MIF_ID,
+  IP6MRA_CREPORT_SRC_ADDR,
+  IP6MRA_CREPORT_DST_ADDR,
+  IP6MRA_CREPORT_PKT,
+  __IP6MRA_CREPORT_MAX
+};
+#define IP6MRA_CREPORT_MAX (__IP6MRA_CREPORT_MAX - 1)
 #endif
diff --git a/libc/kernel/uapi/linux/nbd.h b/libc/kernel/uapi/linux/nbd.h
index 50079fa..749c38a 100644
--- a/libc/kernel/uapi/linux/nbd.h
+++ b/libc/kernel/uapi/linux/nbd.h
@@ -40,8 +40,10 @@
 #define NBD_FLAG_HAS_FLAGS (1 << 0)
 #define NBD_FLAG_READ_ONLY (1 << 1)
 #define NBD_FLAG_SEND_FLUSH (1 << 2)
+#define NBD_FLAG_SEND_FUA (1 << 3)
 #define NBD_FLAG_SEND_TRIM (1 << 5)
 #define NBD_FLAG_CAN_MULTI_CONN (1 << 8)
+#define NBD_CMD_FLAG_FUA (1 << 16)
 #define NBD_CFLAG_DESTROY_ON_DISCONNECT (1 << 0)
 #define NBD_REQUEST_MAGIC 0x25609513
 #define NBD_REPLY_MAGIC 0x67446698
diff --git a/libc/kernel/uapi/linux/ndctl.h b/libc/kernel/uapi/linux/ndctl.h
index cfe5c9c..44c9ee0 100644
--- a/libc/kernel/uapi/linux/ndctl.h
+++ b/libc/kernel/uapi/linux/ndctl.h
@@ -98,7 +98,8 @@
   __u32 status;
   __u32 max_ars_out;
   __u32 clear_err_unit;
-  __u32 reserved;
+  __u16 flags;
+  __u16 reserved;
 } __packed;
 struct nd_cmd_ars_start {
   __u64 address;
@@ -153,6 +154,7 @@
 enum {
   ND_ARS_VOLATILE = 1,
   ND_ARS_PERSISTENT = 2,
+  ND_ARS_RETURN_PREV_DATA = 1 << 1,
   ND_CONFIG_LOCKED = 1,
 };
 #define ND_IOCTL 'N'
diff --git a/libc/kernel/uapi/linux/neighbour.h b/libc/kernel/uapi/linux/neighbour.h
index 1a322de..cf32a12 100644
--- a/libc/kernel/uapi/linux/neighbour.h
+++ b/libc/kernel/uapi/linux/neighbour.h
@@ -50,6 +50,7 @@
 #define NTF_MASTER 0x04
 #define NTF_PROXY 0x08
 #define NTF_EXT_LEARNED 0x10
+#define NTF_OFFLOADED 0x20
 #define NTF_ROUTER 0x80
 #define NUD_INCOMPLETE 0x01
 #define NUD_REACHABLE 0x02
diff --git a/libc/kernel/uapi/linux/net_tstamp.h b/libc/kernel/uapi/linux/net_tstamp.h
index 9a2373e..49d4c2c 100644
--- a/libc/kernel/uapi/linux/net_tstamp.h
+++ b/libc/kernel/uapi/linux/net_tstamp.h
@@ -18,6 +18,7 @@
  ****************************************************************************/
 #ifndef _NET_TIMESTAMPING_H
 #define _NET_TIMESTAMPING_H
+#include <linux/types.h>
 #include <linux/socket.h>
 enum {
   SOF_TIMESTAMPING_TX_HARDWARE = (1 << 0),
@@ -33,7 +34,9 @@
   SOF_TIMESTAMPING_OPT_CMSG = (1 << 10),
   SOF_TIMESTAMPING_OPT_TSONLY = (1 << 11),
   SOF_TIMESTAMPING_OPT_STATS = (1 << 12),
-  SOF_TIMESTAMPING_LAST = SOF_TIMESTAMPING_OPT_STATS,
+  SOF_TIMESTAMPING_OPT_PKTINFO = (1 << 13),
+  SOF_TIMESTAMPING_OPT_TX_SWHW = (1 << 14),
+  SOF_TIMESTAMPING_LAST = SOF_TIMESTAMPING_OPT_TX_SWHW,
   SOF_TIMESTAMPING_MASK = (SOF_TIMESTAMPING_LAST - 1) | SOF_TIMESTAMPING_LAST
 };
 #define SOF_TIMESTAMPING_TX_RECORD_MASK (SOF_TIMESTAMPING_TX_HARDWARE | SOF_TIMESTAMPING_TX_SOFTWARE | SOF_TIMESTAMPING_TX_SCHED | SOF_TIMESTAMPING_TX_ACK)
@@ -63,5 +66,11 @@
   HWTSTAMP_FILTER_PTP_V2_EVENT,
   HWTSTAMP_FILTER_PTP_V2_SYNC,
   HWTSTAMP_FILTER_PTP_V2_DELAY_REQ,
+  HWTSTAMP_FILTER_NTP_ALL,
+};
+struct scm_ts_pktinfo {
+  __u32 if_index;
+  __u32 pkt_length;
+  __u32 reserved[2];
 };
 #endif
diff --git a/libc/kernel/uapi/linux/netfilter/nf_tables.h b/libc/kernel/uapi/linux/netfilter/nf_tables.h
index c090f94..169fb33 100644
--- a/libc/kernel/uapi/linux/netfilter/nf_tables.h
+++ b/libc/kernel/uapi/linux/netfilter/nf_tables.h
@@ -18,10 +18,11 @@
  ****************************************************************************/
 #ifndef _LINUX_NF_TABLES_H
 #define _LINUX_NF_TABLES_H
-#define NFT_TABLE_MAXNAMELEN 32
-#define NFT_CHAIN_MAXNAMELEN 32
-#define NFT_SET_MAXNAMELEN 32
-#define NFT_OBJ_MAXNAMELEN 32
+#define NFT_NAME_MAXLEN 256
+#define NFT_TABLE_MAXNAMELEN NFT_NAME_MAXLEN
+#define NFT_CHAIN_MAXNAMELEN NFT_NAME_MAXLEN
+#define NFT_SET_MAXNAMELEN NFT_NAME_MAXLEN
+#define NFT_OBJ_MAXNAMELEN NFT_NAME_MAXLEN
 #define NFT_USERDATA_MAXLEN 256
 enum nft_registers {
   NFT_REG_VERDICT,
@@ -374,6 +375,7 @@
   NFTA_EXTHDR_LEN,
   NFTA_EXTHDR_FLAGS,
   NFTA_EXTHDR_OP,
+  NFTA_EXTHDR_SREG,
   __NFTA_EXTHDR_MAX
 };
 #define NFTA_EXTHDR_MAX (__NFTA_EXTHDR_MAX - 1)
@@ -408,6 +410,7 @@
   NFT_RT_CLASSID,
   NFT_RT_NEXTHOP4,
   NFT_RT_NEXTHOP6,
+  NFT_RT_TCPMSS,
 };
 enum nft_hash_types {
   NFT_HASH_JENKINS,
@@ -610,6 +613,8 @@
 enum nft_gen_attributes {
   NFTA_GEN_UNSPEC,
   NFTA_GEN_ID,
+  NFTA_GEN_PROC_PID,
+  NFTA_GEN_PROC_NAME,
   __NFTA_GEN_MAX
 };
 #define NFTA_GEN_MAX (__NFTA_GEN_MAX - 1)
@@ -649,7 +654,8 @@
 #define NFT_OBJECT_COUNTER 1
 #define NFT_OBJECT_QUOTA 2
 #define NFT_OBJECT_CT_HELPER 3
-#define __NFT_OBJECT_MAX 4
+#define NFT_OBJECT_LIMIT 4
+#define __NFT_OBJECT_MAX 5
 #define NFT_OBJECT_MAX (__NFT_OBJECT_MAX - 1)
 enum nft_object_attributes {
   NFTA_OBJ_UNSPEC,
diff --git a/libc/kernel/uapi/linux/netfilter/xt_bpf.h b/libc/kernel/uapi/linux/netfilter/xt_bpf.h
index d9a54f9..043af45 100644
--- a/libc/kernel/uapi/linux/netfilter/xt_bpf.h
+++ b/libc/kernel/uapi/linux/netfilter/xt_bpf.h
@@ -34,6 +34,7 @@
   XT_BPF_MODE_FD_PINNED,
   XT_BPF_MODE_FD_ELF,
 };
+#define XT_BPF_MODE_PATH_PINNED XT_BPF_MODE_FD_PINNED
 struct xt_bpf_info_v1 {
   __u16 mode;
   __u16 bpf_program_num_elem;
diff --git a/libc/kernel/uapi/linux/netfilter/xt_hashlimit.h b/libc/kernel/uapi/linux/netfilter/xt_hashlimit.h
index c9d62f3..572c85d 100644
--- a/libc/kernel/uapi/linux/netfilter/xt_hashlimit.h
+++ b/libc/kernel/uapi/linux/netfilter/xt_hashlimit.h
@@ -32,6 +32,7 @@
   XT_HASHLIMIT_HASH_SPT = 1 << 3,
   XT_HASHLIMIT_INVERT = 1 << 4,
   XT_HASHLIMIT_BYTES = 1 << 5,
+  XT_HASHLIMIT_RATE_MATCH = 1 << 6,
 };
 struct hashlimit_cfg {
   __u32 mode;
@@ -71,6 +72,17 @@
   __u32 expire;
   __u8 srcmask, dstmask;
 };
+struct hashlimit_cfg3 {
+  __u64 avg;
+  __u64 burst;
+  __u32 mode;
+  __u32 size;
+  __u32 max;
+  __u32 gc_interval;
+  __u32 expire;
+  __u32 interval;
+  __u8 srcmask, dstmask;
+};
 struct xt_hashlimit_mtinfo1 {
   char name[IFNAMSIZ];
   struct hashlimit_cfg1 cfg;
@@ -81,4 +93,9 @@
   struct hashlimit_cfg2 cfg;
   struct xt_hashlimit_htable * hinfo __attribute__((aligned(8)));
 };
+struct xt_hashlimit_mtinfo3 {
+  char name[NAME_MAX];
+  struct hashlimit_cfg3 cfg;
+  struct xt_hashlimit_htable * hinfo __attribute__((aligned(8)));
+};
 #endif
diff --git a/libc/kernel/uapi/linux/netlink.h b/libc/kernel/uapi/linux/netlink.h
index 4eb428a..4f35c02 100644
--- a/libc/kernel/uapi/linux/netlink.h
+++ b/libc/kernel/uapi/linux/netlink.h
@@ -72,6 +72,7 @@
 #define NLM_F_EXCL 0x200
 #define NLM_F_CREATE 0x400
 #define NLM_F_APPEND 0x800
+#define NLM_F_NONREC 0x100
 #define NLM_F_CAPPED 0x100
 #define NLM_F_ACK_TLVS 0x200
 #define NLMSG_ALIGNTO 4U
@@ -153,4 +154,8 @@
 #define NLA_ALIGNTO 4
 #define NLA_ALIGN(len) (((len) + NLA_ALIGNTO - 1) & ~(NLA_ALIGNTO - 1))
 #define NLA_HDRLEN ((int) NLA_ALIGN(sizeof(struct nlattr)))
+struct nla_bitfield32 {
+  __u32 value;
+  __u32 selector;
+};
 #endif
diff --git a/libc/kernel/uapi/linux/nl80211.h b/libc/kernel/uapi/linux/nl80211.h
index 103b9da..bb9a835 100644
--- a/libc/kernel/uapi/linux/nl80211.h
+++ b/libc/kernel/uapi/linux/nl80211.h
@@ -156,6 +156,8 @@
   NL80211_CMD_NAN_MATCH,
   NL80211_CMD_SET_MULTICAST_TO_UNICAST,
   NL80211_CMD_UPDATE_CONNECT_PARAMS,
+  NL80211_CMD_SET_PMK,
+  NL80211_CMD_DEL_PMK,
   __NL80211_CMD_AFTER_LAST,
   NL80211_CMD_MAX = __NL80211_CMD_AFTER_LAST - 1
 };
@@ -429,6 +431,9 @@
   NL80211_ATTR_PMK,
   NL80211_ATTR_SCHED_SCAN_MULTI,
   NL80211_ATTR_SCHED_SCAN_MAX_REQS,
+  NL80211_ATTR_WANT_1X_4WAY_HS,
+  NL80211_ATTR_PMKR0_NAME,
+  NL80211_ATTR_PORT_AUTHORIZED,
   __NL80211_ATTR_AFTER_LAST,
   NUM_NL80211_ATTR = __NL80211_ATTR_AFTER_LAST,
   NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1
@@ -1187,6 +1192,8 @@
   NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI,
   NL80211_EXT_FEATURE_CQM_RSSI_LIST,
   NL80211_EXT_FEATURE_FILS_SK_OFFLOAD,
+  NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK,
+  NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X,
   NUM_NL80211_EXT_FEATURES,
   MAX_NL80211_EXT_FEATURES = NUM_NL80211_EXT_FEATURES - 1
 };
diff --git a/libc/kernel/uapi/linux/pci_regs.h b/libc/kernel/uapi/linux/pci_regs.h
index baa9421..c7f8381 100644
--- a/libc/kernel/uapi/linux/pci_regs.h
+++ b/libc/kernel/uapi/linux/pci_regs.h
@@ -424,10 +424,12 @@
 #define PCI_EXP_DEVSTA_URD 0x0008
 #define PCI_EXP_DEVSTA_AUXPD 0x0010
 #define PCI_EXP_DEVSTA_TRPND 0x0020
+#define PCI_CAP_EXP_RC_ENDPOINT_SIZEOF_V1 12
 #define PCI_EXP_LNKCAP 12
 #define PCI_EXP_LNKCAP_SLS 0x0000000f
 #define PCI_EXP_LNKCAP_SLS_2_5GB 0x00000001
 #define PCI_EXP_LNKCAP_SLS_5_0GB 0x00000002
+#define PCI_EXP_LNKCAP_SLS_8_0GB 0x00000003
 #define PCI_EXP_LNKCAP_MLW 0x000003f0
 #define PCI_EXP_LNKCAP_ASPMS 0x00000c00
 #define PCI_EXP_LNKCAP_L0SEL 0x00007000
@@ -541,7 +543,7 @@
 #define PCI_EXP_DEVCTL2_OBFF_MSGB_EN 0x4000
 #define PCI_EXP_DEVCTL2_OBFF_WAKE_EN 0x6000
 #define PCI_EXP_DEVSTA2 42
-#define PCI_CAP_EXP_ENDPOINT_SIZEOF_V2 44
+#define PCI_CAP_EXP_RC_ENDPOINT_SIZEOF_V2 44
 #define PCI_EXP_LNKCAP2 44
 #define PCI_EXP_LNKCAP2_SLS_2_5GB 0x00000002
 #define PCI_EXP_LNKCAP2_SLS_5_0GB 0x00000004
@@ -549,6 +551,7 @@
 #define PCI_EXP_LNKCAP2_CROSSLINK 0x00000100
 #define PCI_EXP_LNKCTL2 48
 #define PCI_EXP_LNKSTA2 50
+#define PCI_CAP_EXP_ENDPOINT_SIZEOF_V2 52
 #define PCI_EXP_SLTCAP2 52
 #define PCI_EXP_SLTCTL2 56
 #define PCI_EXP_SLTSTA2 58
@@ -814,6 +817,7 @@
 #define PCI_EXP_DPC_CAP_RP_EXT 0x20
 #define PCI_EXP_DPC_CAP_POISONED_TLP 0x40
 #define PCI_EXP_DPC_CAP_SW_TRIGGER 0x80
+#define PCI_EXP_DPC_RP_PIO_LOG_SIZE 0xF00
 #define PCI_EXP_DPC_CAP_DL_ACTIVE 0x1000
 #define PCI_EXP_DPC_CTL 6
 #define PCI_EXP_DPC_CTL_EN_NONFATAL 0x02
@@ -823,6 +827,14 @@
 #define PCI_EXP_DPC_STATUS_INTERRUPT 0x08
 #define PCI_EXP_DPC_RP_BUSY 0x10
 #define PCI_EXP_DPC_SOURCE_ID 10
+#define PCI_EXP_DPC_RP_PIO_STATUS 0x0C
+#define PCI_EXP_DPC_RP_PIO_MASK 0x10
+#define PCI_EXP_DPC_RP_PIO_SEVERITY 0x14
+#define PCI_EXP_DPC_RP_PIO_SYSERROR 0x18
+#define PCI_EXP_DPC_RP_PIO_EXCEPTION 0x1C
+#define PCI_EXP_DPC_RP_PIO_HEADER_LOG 0x20
+#define PCI_EXP_DPC_RP_PIO_IMPSPEC_LOG 0x30
+#define PCI_EXP_DPC_RP_PIO_TLPPREFIX_LOG 0x34
 #define PCI_PTM_CAP 0x04
 #define PCI_PTM_CAP_REQ 0x00000001
 #define PCI_PTM_CAP_ROOT 0x00000004
diff --git a/libc/kernel/uapi/linux/perf_event.h b/libc/kernel/uapi/linux/perf_event.h
index 8adad9c..326827e 100644
--- a/libc/kernel/uapi/linux/perf_event.h
+++ b/libc/kernel/uapi/linux/perf_event.h
@@ -98,7 +98,8 @@
   PERF_SAMPLE_IDENTIFIER = 1U << 16,
   PERF_SAMPLE_TRANSACTION = 1U << 17,
   PERF_SAMPLE_REGS_INTR = 1U << 18,
-  PERF_SAMPLE_MAX = 1U << 19,
+  PERF_SAMPLE_PHYS_ADDR = 1U << 19,
+  PERF_SAMPLE_MAX = 1U << 20,
 };
 enum perf_branch_sample_type_shift {
   PERF_SAMPLE_BRANCH_USER_SHIFT = 0,
@@ -117,6 +118,7 @@
   PERF_SAMPLE_BRANCH_CALL_SHIFT = 13,
   PERF_SAMPLE_BRANCH_NO_FLAGS_SHIFT = 14,
   PERF_SAMPLE_BRANCH_NO_CYCLES_SHIFT = 15,
+  PERF_SAMPLE_BRANCH_TYPE_SAVE_SHIFT = 16,
   PERF_SAMPLE_BRANCH_MAX_SHIFT
 };
 enum perf_branch_sample_type {
@@ -136,8 +138,23 @@
   PERF_SAMPLE_BRANCH_CALL = 1U << PERF_SAMPLE_BRANCH_CALL_SHIFT,
   PERF_SAMPLE_BRANCH_NO_FLAGS = 1U << PERF_SAMPLE_BRANCH_NO_FLAGS_SHIFT,
   PERF_SAMPLE_BRANCH_NO_CYCLES = 1U << PERF_SAMPLE_BRANCH_NO_CYCLES_SHIFT,
+  PERF_SAMPLE_BRANCH_TYPE_SAVE = 1U << PERF_SAMPLE_BRANCH_TYPE_SAVE_SHIFT,
   PERF_SAMPLE_BRANCH_MAX = 1U << PERF_SAMPLE_BRANCH_MAX_SHIFT,
 };
+enum {
+  PERF_BR_UNKNOWN = 0,
+  PERF_BR_COND = 1,
+  PERF_BR_UNCOND = 2,
+  PERF_BR_IND = 3,
+  PERF_BR_CALL = 4,
+  PERF_BR_IND_CALL = 5,
+  PERF_BR_RET = 6,
+  PERF_BR_SYSCALL = 7,
+  PERF_BR_SYSRET = 8,
+  PERF_BR_COND_CALL = 9,
+  PERF_BR_COND_RET = 10,
+  PERF_BR_MAX,
+};
 #define PERF_SAMPLE_BRANCH_PLM_ALL (PERF_SAMPLE_BRANCH_USER | PERF_SAMPLE_BRANCH_KERNEL | PERF_SAMPLE_BRANCH_HV)
 enum perf_sample_regs_abi {
   PERF_SAMPLE_REGS_ABI_NONE = 0,
@@ -320,14 +337,14 @@
 union perf_mem_data_src {
   __u64 val;
   struct {
-    __u64 mem_op : 5, mem_lvl : 14, mem_snoop : 5, mem_lock : 2, mem_dtlb : 7, mem_rsvd : 31;
+    __u64 mem_op : 5, mem_lvl : 14, mem_snoop : 5, mem_lock : 2, mem_dtlb : 7, mem_lvl_num : 4, mem_remote : 1, mem_snoopx : 2, mem_rsvd : 24;
   };
 };
 #elif defined(__BIG_ENDIAN_BITFIELD)
 union perf_mem_data_src {
   __u64 val;
   struct {
-    __u64 mem_rsvd : 31, mem_dtlb : 7, mem_lock : 2, mem_snoop : 5, mem_lvl : 14, mem_op : 5;
+    __u64 mem_rsvd : 24, mem_snoopx : 2, mem_remote : 1, mem_lvl_num : 4, mem_dtlb : 7, mem_lock : 2, mem_snoop : 5, mem_lvl : 14, mem_op : 5;
   };
 };
 #else
@@ -354,12 +371,26 @@
 #define PERF_MEM_LVL_IO 0x1000
 #define PERF_MEM_LVL_UNC 0x2000
 #define PERF_MEM_LVL_SHIFT 5
+#define PERF_MEM_REMOTE_REMOTE 0x01
+#define PERF_MEM_REMOTE_SHIFT 37
+#define PERF_MEM_LVLNUM_L1 0x01
+#define PERF_MEM_LVLNUM_L2 0x02
+#define PERF_MEM_LVLNUM_L3 0x03
+#define PERF_MEM_LVLNUM_L4 0x04
+#define PERF_MEM_LVLNUM_ANY_CACHE 0x0b
+#define PERF_MEM_LVLNUM_LFB 0x0c
+#define PERF_MEM_LVLNUM_RAM 0x0d
+#define PERF_MEM_LVLNUM_PMEM 0x0e
+#define PERF_MEM_LVLNUM_NA 0x0f
+#define PERF_MEM_LVLNUM_SHIFT 33
 #define PERF_MEM_SNOOP_NA 0x01
 #define PERF_MEM_SNOOP_NONE 0x02
 #define PERF_MEM_SNOOP_HIT 0x04
 #define PERF_MEM_SNOOP_MISS 0x08
 #define PERF_MEM_SNOOP_HITM 0x10
 #define PERF_MEM_SNOOP_SHIFT 19
+#define PERF_MEM_SNOOPX_FWD 0x01
+#define PERF_MEM_SNOOPX_SHIFT 37
 #define PERF_MEM_LOCK_NA 0x01
 #define PERF_MEM_LOCK_LOCKED 0x02
 #define PERF_MEM_LOCK_SHIFT 24
@@ -375,6 +406,6 @@
 struct perf_branch_entry {
   __u64 from;
   __u64 to;
-  __u64 mispred : 1, predicted : 1, in_tx : 1, abort : 1, cycles : 16, reserved : 44;
+  __u64 mispred : 1, predicted : 1, in_tx : 1, abort : 1, cycles : 16, type : 4, reserved : 40;
 };
 #endif
diff --git a/libc/kernel/uapi/linux/pkt_cls.h b/libc/kernel/uapi/linux/pkt_cls.h
index af251c0..4bac8f9 100644
--- a/libc/kernel/uapi/linux/pkt_cls.h
+++ b/libc/kernel/uapi/linux/pkt_cls.h
@@ -49,11 +49,13 @@
 #define TC_ACT_QUEUED 5
 #define TC_ACT_REPEAT 6
 #define TC_ACT_REDIRECT 7
+#define TC_ACT_TRAP 8
 #define __TC_ACT_EXT_SHIFT 28
 #define __TC_ACT_EXT(local) ((local) << __TC_ACT_EXT_SHIFT)
 #define TC_ACT_EXT_VAL_MASK ((1 << __TC_ACT_EXT_SHIFT) - 1)
 #define TC_ACT_EXT_CMP(combined,opcode) (((combined) & (~TC_ACT_EXT_VAL_MASK)) == opcode)
 #define TC_ACT_JUMP __TC_ACT_EXT(1)
+#define TC_ACT_GOTO_CHAIN __TC_ACT_EXT(2)
 enum {
   TCA_ID_UNSPEC = 0,
   TCA_ID_POLICE = 1,
@@ -291,6 +293,7 @@
   TCA_BPF_FLAGS,
   TCA_BPF_FLAGS_GEN,
   TCA_BPF_TAG,
+  TCA_BPF_ID,
   __TCA_BPF_MAX,
 };
 #define TCA_BPF_MAX (__TCA_BPF_MAX - 1)
@@ -366,6 +369,12 @@
   TCA_FLOWER_KEY_MPLS_BOS,
   TCA_FLOWER_KEY_MPLS_TC,
   TCA_FLOWER_KEY_MPLS_LABEL,
+  TCA_FLOWER_KEY_TCP_FLAGS,
+  TCA_FLOWER_KEY_TCP_FLAGS_MASK,
+  TCA_FLOWER_KEY_IP_TOS,
+  TCA_FLOWER_KEY_IP_TOS_MASK,
+  TCA_FLOWER_KEY_IP_TTL,
+  TCA_FLOWER_KEY_IP_TTL_MASK,
   __TCA_FLOWER_MAX,
 };
 #define TCA_FLOWER_MAX (__TCA_FLOWER_MAX - 1)
diff --git a/libc/kernel/uapi/linux/quota.h b/libc/kernel/uapi/linux/quota.h
index cc5ccbb..280b396 100644
--- a/libc/kernel/uapi/linux/quota.h
+++ b/libc/kernel/uapi/linux/quota.h
@@ -18,7 +18,6 @@
  ****************************************************************************/
 #ifndef _UAPI_LINUX_QUOTA_
 #define _UAPI_LINUX_QUOTA_
-#include <linux/errno.h>
 #include <linux/types.h>
 #define __DQUOT_VERSION__ "dquot_6.6.0"
 #define MAXQUOTAS 3
diff --git a/libc/kernel/uapi/linux/raid/md_p.h b/libc/kernel/uapi/linux/raid/md_p.h
index ea54bdb..0bc6756 100644
--- a/libc/kernel/uapi/linux/raid/md_p.h
+++ b/libc/kernel/uapi/linux/raid/md_p.h
@@ -181,7 +181,8 @@
 #define MD_FEATURE_CLUSTERED 256
 #define MD_FEATURE_JOURNAL 512
 #define MD_FEATURE_PPL 1024
-#define MD_FEATURE_ALL (MD_FEATURE_BITMAP_OFFSET | MD_FEATURE_RECOVERY_OFFSET | MD_FEATURE_RESHAPE_ACTIVE | MD_FEATURE_BAD_BLOCKS | MD_FEATURE_REPLACEMENT | MD_FEATURE_RESHAPE_BACKWARDS | MD_FEATURE_NEW_OFFSET | MD_FEATURE_RECOVERY_BITMAP | MD_FEATURE_CLUSTERED | MD_FEATURE_JOURNAL | MD_FEATURE_PPL)
+#define MD_FEATURE_MULTIPLE_PPLS 2048
+#define MD_FEATURE_ALL (MD_FEATURE_BITMAP_OFFSET | MD_FEATURE_RECOVERY_OFFSET | MD_FEATURE_RESHAPE_ACTIVE | MD_FEATURE_BAD_BLOCKS | MD_FEATURE_REPLACEMENT | MD_FEATURE_RESHAPE_BACKWARDS | MD_FEATURE_NEW_OFFSET | MD_FEATURE_RECOVERY_BITMAP | MD_FEATURE_CLUSTERED | MD_FEATURE_JOURNAL | MD_FEATURE_PPL | MD_FEATURE_MULTIPLE_PPLS)
 struct r5l_payload_header {
   __le16 type;
   __le16 flags;
diff --git a/libc/kernel/uapi/linux/rtnetlink.h b/libc/kernel/uapi/linux/rtnetlink.h
index d094068..c363e34 100644
--- a/libc/kernel/uapi/linux/rtnetlink.h
+++ b/libc/kernel/uapi/linux/rtnetlink.h
@@ -131,6 +131,8 @@
 #define RTM_NEWSTATS RTM_NEWSTATS
   RTM_GETSTATS = 94,
 #define RTM_GETSTATS RTM_GETSTATS
+  RTM_NEWCACHEREPORT = 96,
+#define RTM_NEWCACHEREPORT RTM_NEWCACHEREPORT
   __RTM_MAX,
 #define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1)
 };
@@ -204,6 +206,7 @@
 #define RTM_F_EQUALIZE 0x400
 #define RTM_F_PREFIX 0x800
 #define RTM_F_LOOKUP_TABLE 0x1000
+#define RTM_F_FIB_MATCH 0x2000
 enum rt_class_t {
   RT_TABLE_UNSPEC = 0,
   RT_TABLE_COMPAT = 252,
@@ -398,6 +401,7 @@
   TCA_STAB,
   TCA_PAD,
   TCA_DUMP_INVISIBLE,
+  TCA_CHAIN,
   __TCA_MAX
 };
 #define TCA_MAX (__TCA_MAX - 1)
@@ -493,6 +497,10 @@
 #define RTNLGRP_NSID RTNLGRP_NSID
   RTNLGRP_MPLS_NETCONF,
 #define RTNLGRP_MPLS_NETCONF RTNLGRP_MPLS_NETCONF
+  RTNLGRP_IPV4_MROUTE_R,
+#define RTNLGRP_IPV4_MROUTE_R RTNLGRP_IPV4_MROUTE_R
+  RTNLGRP_IPV6_MROUTE_R,
+#define RTNLGRP_IPV6_MROUTE_R RTNLGRP_IPV6_MROUTE_R
   __RTNLGRP_MAX
 };
 #define RTNLGRP_MAX (__RTNLGRP_MAX - 1)
@@ -501,10 +509,20 @@
   unsigned char tca__pad1;
   unsigned short tca__pad2;
 };
+enum {
+  TCA_ROOT_UNSPEC,
+  TCA_ROOT_TAB,
+#define TCA_ACT_TAB TCA_ROOT_TAB
+#define TCAA_MAX TCA_ROOT_TAB
+  TCA_ROOT_FLAGS,
+  TCA_ROOT_COUNT,
+  TCA_ROOT_TIME_DELTA,
+  __TCA_ROOT_MAX,
+#define TCA_ROOT_MAX (__TCA_ROOT_MAX - 1)
+};
 #define TA_RTA(r) ((struct rtattr *) (((char *) (r)) + NLMSG_ALIGN(sizeof(struct tcamsg))))
 #define TA_PAYLOAD(n) NLMSG_PAYLOAD(n, sizeof(struct tcamsg))
-#define TCA_ACT_TAB 1
-#define TCAA_MAX 1
+#define TCA_FLAG_LARGE_DUMP_ON (1 << 0)
 #define RTEXT_FILTER_VF (1 << 0)
 #define RTEXT_FILTER_BRVLAN (1 << 1)
 #define RTEXT_FILTER_BRVLAN_COMPRESSED (1 << 2)
diff --git a/libc/kernel/uapi/linux/rxrpc.h b/libc/kernel/uapi/linux/rxrpc.h
new file mode 100644
index 0000000..b8b7b04
--- /dev/null
+++ b/libc/kernel/uapi/linux/rxrpc.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ***   To edit the content of this header, modify the corresponding
+ ***   source file (e.g. under external/kernel-headers/original/) then
+ ***   run bionic/libc/kernel/tools/update_all.py
+ ***
+ ***   Any manual change here will be lost the next time this script will
+ ***   be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _UAPI_LINUX_RXRPC_H
+#define _UAPI_LINUX_RXRPC_H
+#include <linux/types.h>
+#include <linux/in.h>
+#include <linux/in6.h>
+struct sockaddr_rxrpc {
+  sa_family_t srx_family;
+  u16 srx_service;
+  u16 transport_type;
+  u16 transport_len;
+  union {
+    sa_family_t family;
+    struct sockaddr_in sin;
+    struct sockaddr_in6 sin6;
+  } transport;
+};
+#define RXRPC_SECURITY_KEY 1
+#define RXRPC_SECURITY_KEYRING 2
+#define RXRPC_EXCLUSIVE_CONNECTION 3
+#define RXRPC_MIN_SECURITY_LEVEL 4
+#define RXRPC_UPGRADEABLE_SERVICE 5
+#define RXRPC_SUPPORTED_CMSG 6
+enum rxrpc_cmsg_type {
+  RXRPC_USER_CALL_ID = 1,
+  RXRPC_ABORT = 2,
+  RXRPC_ACK = 3,
+  RXRPC_NET_ERROR = 5,
+  RXRPC_BUSY = 6,
+  RXRPC_LOCAL_ERROR = 7,
+  RXRPC_NEW_CALL = 8,
+  RXRPC_ACCEPT = 9,
+  RXRPC_EXCLUSIVE_CALL = 10,
+  RXRPC_UPGRADE_SERVICE = 11,
+  RXRPC_TX_LENGTH = 12,
+  RXRPC__SUPPORTED
+};
+#define RXRPC_SECURITY_PLAIN 0
+#define RXRPC_SECURITY_AUTH 1
+#define RXRPC_SECURITY_ENCRYPT 2
+#define RXRPC_SECURITY_NONE 0
+#define RXRPC_SECURITY_RXKAD 2
+#define RXRPC_SECURITY_RXGK 4
+#define RXRPC_SECURITY_RXK5 5
+#define RX_CALL_DEAD - 1
+#define RX_INVALID_OPERATION - 2
+#define RX_CALL_TIMEOUT - 3
+#define RX_EOF - 4
+#define RX_PROTOCOL_ERROR - 5
+#define RX_USER_ABORT - 6
+#define RX_ADDRINUSE - 7
+#define RX_DEBUGI_BADTYPE - 8
+#define RXGEN_CC_MARSHAL - 450
+#define RXGEN_CC_UNMARSHAL - 451
+#define RXGEN_SS_MARSHAL - 452
+#define RXGEN_SS_UNMARSHAL - 453
+#define RXGEN_DECODE - 454
+#define RXGEN_OPCODE - 455
+#define RXGEN_SS_XDRFREE - 456
+#define RXGEN_CC_XDRFREE - 457
+#define RXKADINCONSISTENCY 19270400
+#define RXKADPACKETSHORT 19270401
+#define RXKADLEVELFAIL 19270402
+#define RXKADTICKETLEN 19270403
+#define RXKADOUTOFSEQUENCE 19270404
+#define RXKADNOAUTH 19270405
+#define RXKADBADKEY 19270406
+#define RXKADBADTICKET 19270407
+#define RXKADUNKNOWNKEY 19270408
+#define RXKADEXPIRED 19270409
+#define RXKADSEALEDINCON 19270410
+#define RXKADDATALEN 19270411
+#define RXKADILLEGALLEVEL 19270412
+#endif
diff --git a/libc/kernel/uapi/linux/sched.h b/libc/kernel/uapi/linux/sched.h
index 8d149b8..9958fba 100644
--- a/libc/kernel/uapi/linux/sched.h
+++ b/libc/kernel/uapi/linux/sched.h
@@ -50,4 +50,5 @@
 #define SCHED_DEADLINE 6
 #define SCHED_RESET_ON_FORK 0x40000000
 #define SCHED_FLAG_RESET_ON_FORK 0x01
+#define SCHED_FLAG_RECLAIM 0x02
 #endif
diff --git a/libc/kernel/uapi/linux/sctp.h b/libc/kernel/uapi/linux/sctp.h
index a5cef43..9a55459 100644
--- a/libc/kernel/uapi/linux/sctp.h
+++ b/libc/kernel/uapi/linux/sctp.h
@@ -76,6 +76,7 @@
 #define SCTP_RESET_STREAMS 119
 #define SCTP_RESET_ASSOC 120
 #define SCTP_ADD_STREAMS 121
+#define SCTP_SOCKOPT_PEELOFF_FLAGS 122
 #define SCTP_PR_SCTP_NONE 0x0000
 #define SCTP_PR_SCTP_TTL 0x0010
 #define SCTP_PR_SCTP_RTX 0x0020
@@ -204,7 +205,7 @@
   __u16 sre_type;
   __u16 sre_flags;
   __u32 sre_length;
-  __u16 sre_error;
+  __be16 sre_error;
   sctp_assoc_t sre_assoc_id;
   __u8 sre_data[0];
 };
@@ -525,6 +526,10 @@
   sctp_assoc_t associd;
   int sd;
 } sctp_peeloff_arg_t;
+typedef struct {
+  sctp_peeloff_arg_t p_arg;
+  unsigned flags;
+} sctp_peeloff_flags_arg_t;
 struct sctp_paddrthlds {
   sctp_assoc_t spt_assoc_id;
   struct sockaddr_storage spt_address;
diff --git a/libc/kernel/uapi/linux/seccomp.h b/libc/kernel/uapi/linux/seccomp.h
index db041a3..1fd53fc 100644
--- a/libc/kernel/uapi/linux/seccomp.h
+++ b/libc/kernel/uapi/linux/seccomp.h
@@ -25,12 +25,18 @@
 #define SECCOMP_MODE_FILTER 2
 #define SECCOMP_SET_MODE_STRICT 0
 #define SECCOMP_SET_MODE_FILTER 1
+#define SECCOMP_GET_ACTION_AVAIL 2
 #define SECCOMP_FILTER_FLAG_TSYNC 1
-#define SECCOMP_RET_KILL 0x00000000U
+#define SECCOMP_FILTER_FLAG_LOG 2
+#define SECCOMP_RET_KILL_PROCESS 0x80000000U
+#define SECCOMP_RET_KILL_THREAD 0x00000000U
+#define SECCOMP_RET_KILL SECCOMP_RET_KILL_THREAD
 #define SECCOMP_RET_TRAP 0x00030000U
 #define SECCOMP_RET_ERRNO 0x00050000U
 #define SECCOMP_RET_TRACE 0x7ff00000U
+#define SECCOMP_RET_LOG 0x7ffc0000U
 #define SECCOMP_RET_ALLOW 0x7fff0000U
+#define SECCOMP_RET_ACTION_FULL 0xffff0000U
 #define SECCOMP_RET_ACTION 0x7fff0000U
 #define SECCOMP_RET_DATA 0x0000ffffU
 struct seccomp_data {
diff --git a/libc/kernel/uapi/linux/seg6_iptunnel.h b/libc/kernel/uapi/linux/seg6_iptunnel.h
index 747fa09..1c1ad83 100644
--- a/libc/kernel/uapi/linux/seg6_iptunnel.h
+++ b/libc/kernel/uapi/linux/seg6_iptunnel.h
@@ -33,5 +33,6 @@
 enum {
   SEG6_IPTUN_MODE_INLINE,
   SEG6_IPTUN_MODE_ENCAP,
+  SEG6_IPTUN_MODE_L2ENCAP,
 };
 #endif
diff --git a/libc/kernel/uapi/linux/seg6_local.h b/libc/kernel/uapi/linux/seg6_local.h
new file mode 100644
index 0000000..7a10701
--- /dev/null
+++ b/libc/kernel/uapi/linux/seg6_local.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ***   To edit the content of this header, modify the corresponding
+ ***   source file (e.g. under external/kernel-headers/original/) then
+ ***   run bionic/libc/kernel/tools/update_all.py
+ ***
+ ***   Any manual change here will be lost the next time this script will
+ ***   be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _UAPI_LINUX_SEG6_LOCAL_H
+#define _UAPI_LINUX_SEG6_LOCAL_H
+#include <linux/seg6.h>
+enum {
+  SEG6_LOCAL_UNSPEC,
+  SEG6_LOCAL_ACTION,
+  SEG6_LOCAL_SRH,
+  SEG6_LOCAL_TABLE,
+  SEG6_LOCAL_NH4,
+  SEG6_LOCAL_NH6,
+  SEG6_LOCAL_IIF,
+  SEG6_LOCAL_OIF,
+  __SEG6_LOCAL_MAX,
+};
+#define SEG6_LOCAL_MAX (__SEG6_LOCAL_MAX - 1)
+enum {
+  SEG6_LOCAL_ACTION_UNSPEC = 0,
+  SEG6_LOCAL_ACTION_END = 1,
+  SEG6_LOCAL_ACTION_END_X = 2,
+  SEG6_LOCAL_ACTION_END_T = 3,
+  SEG6_LOCAL_ACTION_END_DX2 = 4,
+  SEG6_LOCAL_ACTION_END_DX6 = 5,
+  SEG6_LOCAL_ACTION_END_DX4 = 6,
+  SEG6_LOCAL_ACTION_END_DT6 = 7,
+  SEG6_LOCAL_ACTION_END_DT4 = 8,
+  SEG6_LOCAL_ACTION_END_B6 = 9,
+  SEG6_LOCAL_ACTION_END_B6_ENCAP = 10,
+  SEG6_LOCAL_ACTION_END_BM = 11,
+  SEG6_LOCAL_ACTION_END_S = 12,
+  SEG6_LOCAL_ACTION_END_AS = 13,
+  SEG6_LOCAL_ACTION_END_AM = 14,
+  __SEG6_LOCAL_ACTION_MAX,
+};
+#define SEG6_LOCAL_ACTION_MAX (__SEG6_LOCAL_ACTION_MAX - 1)
+#endif
diff --git a/libc/kernel/uapi/linux/serial.h b/libc/kernel/uapi/linux/serial.h
index 219a2ea..79f11e3 100644
--- a/libc/kernel/uapi/linux/serial.h
+++ b/libc/kernel/uapi/linux/serial.h
@@ -95,6 +95,7 @@
 #define SER_RS485_RTS_ON_SEND (1 << 1)
 #define SER_RS485_RTS_AFTER_SEND (1 << 2)
 #define SER_RS485_RX_DURING_TX (1 << 4)
+#define SER_RS485_TERMINATE_BUS (1 << 5)
   __u32 delay_rts_before_send;
   __u32 delay_rts_after_send;
   __u32 padding[5];
diff --git a/libc/kernel/uapi/linux/serial_core.h b/libc/kernel/uapi/linux/serial_core.h
index af349c2..68d2dcb 100644
--- a/libc/kernel/uapi/linux/serial_core.h
+++ b/libc/kernel/uapi/linux/serial_core.h
@@ -50,16 +50,17 @@
 #define PORT_ALTR_16550_F128 28
 #define PORT_RT2880 29
 #define PORT_16550A_FSL64 30
-#define PORT_DA830 31
-#define PORT_MAX_8250 31
 #define PORT_PXA 31
 #define PORT_AMBA 32
 #define PORT_CLPS711X 33
 #define PORT_SA1100 34
 #define PORT_UART00 35
+#define PORT_OWL 36
 #define PORT_21285 37
 #define PORT_SUNZILOG 38
 #define PORT_SUNSAB 39
+#define PORT_PCH_8LINE 44
+#define PORT_PCH_2LINE 45
 #define PORT_DZ 46
 #define PORT_ZS 47
 #define PORT_MUX 48
@@ -109,7 +110,7 @@
 #define PORT_ALTERA_UART 92
 #define PORT_SCIFB 93
 #define PORT_MAX310X 94
-#define PORT_MFD 95
+#define PORT_DA830 95
 #define PORT_OMAP 96
 #define PORT_VT8500 97
 #define PORT_XUARTPS 98
@@ -131,4 +132,5 @@
 #define PORT_MVEBU 114
 #define PORT_PIC32 115
 #define PORT_MPS2UART 116
+#define PORT_MTK_BTIF 117
 #endif
diff --git a/libc/kernel/uapi/linux/shm.h b/libc/kernel/uapi/linux/shm.h
index ab319f2..a3071e7 100644
--- a/libc/kernel/uapi/linux/shm.h
+++ b/libc/kernel/uapi/linux/shm.h
@@ -20,6 +20,7 @@
 #define _UAPI_LINUX_SHM_H_
 #include <linux/ipc.h>
 #include <linux/errno.h>
+#include <asm-generic/hugetlb_encode.h>
 #include <unistd.h>
 #define SHMMIN 1
 #define SHMMNI 4096
@@ -42,6 +43,20 @@
 #include <asm/shmbuf.h>
 #define SHM_R 0400
 #define SHM_W 0200
+#define SHM_HUGETLB 04000
+#define SHM_NORESERVE 010000
+#define SHM_HUGE_SHIFT HUGETLB_FLAG_ENCODE_SHIFT
+#define SHM_HUGE_MASK HUGETLB_FLAG_ENCODE_MASK
+#define SHM_HUGE_64KB HUGETLB_FLAG_ENCODE_64KB
+#define SHM_HUGE_512KB HUGETLB_FLAG_ENCODE_512KB
+#define SHM_HUGE_1MB HUGETLB_FLAG_ENCODE_1MB
+#define SHM_HUGE_2MB HUGETLB_FLAG_ENCODE_2MB
+#define SHM_HUGE_8MB HUGETLB_FLAG_ENCODE_8MB
+#define SHM_HUGE_16MB HUGETLB_FLAG_ENCODE_16MB
+#define SHM_HUGE_256MB HUGETLB_FLAG_ENCODE_256MB
+#define SHM_HUGE_1GB HUGETLB_FLAG_ENCODE_1GB
+#define SHM_HUGE_2GB HUGETLB_FLAG_ENCODE_2GB
+#define SHM_HUGE_16GB HUGETLB_FLAG_ENCODE_16GB
 #define SHM_RDONLY 010000
 #define SHM_RND 020000
 #define SHM_REMAP 040000
diff --git a/libc/kernel/uapi/linux/snmp.h b/libc/kernel/uapi/linux/snmp.h
index 91d693f..467a27a 100644
--- a/libc/kernel/uapi/linux/snmp.h
+++ b/libc/kernel/uapi/linux/snmp.h
@@ -152,12 +152,7 @@
   LINUX_MIB_DELAYEDACKLOST,
   LINUX_MIB_LISTENOVERFLOWS,
   LINUX_MIB_LISTENDROPS,
-  LINUX_MIB_TCPPREQUEUED,
-  LINUX_MIB_TCPDIRECTCOPYFROMBACKLOG,
-  LINUX_MIB_TCPDIRECTCOPYFROMPREQUEUE,
-  LINUX_MIB_TCPPREQUEUEDROPPED,
   LINUX_MIB_TCPHPHITS,
-  LINUX_MIB_TCPHPHITSTOUSER,
   LINUX_MIB_TCPPUREACKS,
   LINUX_MIB_TCPHPACKS,
   LINUX_MIB_TCPRENORECOVERY,
@@ -176,14 +171,12 @@
   LINUX_MIB_TCPSACKFAILURES,
   LINUX_MIB_TCPLOSSFAILURES,
   LINUX_MIB_TCPFASTRETRANS,
-  LINUX_MIB_TCPFORWARDRETRANS,
   LINUX_MIB_TCPSLOWSTARTRETRANS,
   LINUX_MIB_TCPTIMEOUTS,
   LINUX_MIB_TCPLOSSPROBES,
   LINUX_MIB_TCPLOSSPROBERECOVERY,
   LINUX_MIB_TCPRENORECOVERYFAIL,
   LINUX_MIB_TCPSACKRECOVERYFAIL,
-  LINUX_MIB_TCPSCHEDULERFAILED,
   LINUX_MIB_TCPRCVCOLLAPSED,
   LINUX_MIB_TCPDSACKOLDSENT,
   LINUX_MIB_TCPDSACKOFOSENT,
@@ -196,6 +189,7 @@
   LINUX_MIB_TCPABORTONLINGER,
   LINUX_MIB_TCPABORTFAILED,
   LINUX_MIB_TCPMEMORYPRESSURES,
+  LINUX_MIB_TCPMEMORYPRESSURESCHRONO,
   LINUX_MIB_TCPSACKDISCARD,
   LINUX_MIB_TCPDSACKIGNOREDOLD,
   LINUX_MIB_TCPDSACKIGNOREDNOUNDO,
diff --git a/libc/kernel/uapi/linux/spi/spidev.h b/libc/kernel/uapi/linux/spi/spidev.h
index 73efc6f..2fe8264 100644
--- a/libc/kernel/uapi/linux/spi/spidev.h
+++ b/libc/kernel/uapi/linux/spi/spidev.h
@@ -19,6 +19,7 @@
 #ifndef SPIDEV_H
 #define SPIDEV_H
 #include <linux/types.h>
+#include <linux/ioctl.h>
 #define SPI_CPHA 0x01
 #define SPI_CPOL 0x02
 #define SPI_MODE_0 (0 | 0)
diff --git a/libc/kernel/uapi/linux/switchtec_ioctl.h b/libc/kernel/uapi/linux/switchtec_ioctl.h
index a0341a8..9337be6 100644
--- a/libc/kernel/uapi/linux/switchtec_ioctl.h
+++ b/libc/kernel/uapi/linux/switchtec_ioctl.h
@@ -38,6 +38,8 @@
   __u32 num_partitions;
   __u32 padding;
 };
+#define SWITCHTEC_IOCTL_PART_ACTIVE 1
+#define SWITCHTEC_IOCTL_PART_RUNNING 2
 struct switchtec_ioctl_flash_part_info {
   __u32 flash_partition;
   __u32 address;
diff --git a/libc/kernel/uapi/linux/target_core_user.h b/libc/kernel/uapi/linux/target_core_user.h
index 640e9c7..264b46f 100644
--- a/libc/kernel/uapi/linux/target_core_user.h
+++ b/libc/kernel/uapi/linux/target_core_user.h
@@ -71,6 +71,11 @@
   TCMU_CMD_UNSPEC,
   TCMU_CMD_ADDED_DEVICE,
   TCMU_CMD_REMOVED_DEVICE,
+  TCMU_CMD_RECONFIG_DEVICE,
+  TCMU_CMD_ADDED_DEVICE_DONE,
+  TCMU_CMD_REMOVED_DEVICE_DONE,
+  TCMU_CMD_RECONFIG_DEVICE_DONE,
+  TCMU_CMD_SET_FEATURES,
   __TCMU_CMD_MAX,
 };
 #define TCMU_CMD_MAX (__TCMU_CMD_MAX - 1)
@@ -78,6 +83,13 @@
   TCMU_ATTR_UNSPEC,
   TCMU_ATTR_DEVICE,
   TCMU_ATTR_MINOR,
+  TCMU_ATTR_PAD,
+  TCMU_ATTR_DEV_CFG,
+  TCMU_ATTR_DEV_SIZE,
+  TCMU_ATTR_WRITECACHE,
+  TCMU_ATTR_CMD_STATUS,
+  TCMU_ATTR_DEVICE_ID,
+  TCMU_ATTR_SUPP_KERN_CMD_REPLY,
   __TCMU_ATTR_MAX,
 };
 #define TCMU_ATTR_MAX (__TCMU_ATTR_MAX - 1)
diff --git a/libc/kernel/uapi/linux/tc_act/tc_bpf.h b/libc/kernel/uapi/linux/tc_act/tc_bpf.h
index 2e6f6d1..c4963a5 100644
--- a/libc/kernel/uapi/linux/tc_act/tc_bpf.h
+++ b/libc/kernel/uapi/linux/tc_act/tc_bpf.h
@@ -33,6 +33,7 @@
   TCA_ACT_BPF_NAME,
   TCA_ACT_BPF_PAD,
   TCA_ACT_BPF_TAG,
+  TCA_ACT_BPF_ID,
   __TCA_ACT_BPF_MAX,
 };
 #define TCA_ACT_BPF_MAX (__TCA_ACT_BPF_MAX - 1)
diff --git a/libc/kernel/uapi/linux/tc_act/tc_tunnel_key.h b/libc/kernel/uapi/linux/tc_act/tc_tunnel_key.h
index 014a584..24e7403 100644
--- a/libc/kernel/uapi/linux/tc_act/tc_tunnel_key.h
+++ b/libc/kernel/uapi/linux/tc_act/tc_tunnel_key.h
@@ -37,6 +37,7 @@
   TCA_TUNNEL_KEY_ENC_KEY_ID,
   TCA_TUNNEL_KEY_PAD,
   TCA_TUNNEL_KEY_ENC_DST_PORT,
+  TCA_TUNNEL_KEY_NO_CSUM,
   __TCA_TUNNEL_KEY_MAX,
 };
 #define TCA_TUNNEL_KEY_MAX (__TCA_TUNNEL_KEY_MAX - 1)
diff --git a/libc/kernel/uapi/linux/tcp.h b/libc/kernel/uapi/linux/tcp.h
index 9c3a90d..f5134d6 100644
--- a/libc/kernel/uapi/linux/tcp.h
+++ b/libc/kernel/uapi/linux/tcp.h
@@ -85,6 +85,8 @@
 #define TCP_SAVED_SYN 28
 #define TCP_REPAIR_WINDOW 29
 #define TCP_FASTOPEN_CONNECT 30
+#define TCP_ULP 31
+#define TCP_MD5SIG_EXT 32
 struct tcp_repair_opt {
   __u32 opt_code;
   __u32 opt_val;
@@ -175,13 +177,29 @@
   TCP_NLA_SNDBUF_LIMITED,
   TCP_NLA_DATA_SEGS_OUT,
   TCP_NLA_TOTAL_RETRANS,
+  TCP_NLA_PACING_RATE,
+  TCP_NLA_DELIVERY_RATE,
+  TCP_NLA_SND_CWND,
+  TCP_NLA_REORDERING,
+  TCP_NLA_MIN_RTT,
+  TCP_NLA_RECUR_RETRANS,
+  TCP_NLA_DELIVERY_RATE_APP_LMT,
 };
 #define TCP_MD5SIG_MAXKEYLEN 80
+#define TCP_MD5SIG_FLAG_PREFIX 1
 struct tcp_md5sig {
   struct __kernel_sockaddr_storage tcpm_addr;
-  __u16 __tcpm_pad1;
+  __u8 tcpm_flags;
+  __u8 tcpm_prefixlen;
   __u16 tcpm_keylen;
-  __u32 __tcpm_pad2;
+  __u32 __tcpm_pad;
+  __u8 tcpm_key[TCP_MD5SIG_MAXKEYLEN];
+};
+struct tcp_diag_md5sig {
+  __u8 tcpm_family;
+  __u8 tcpm_prefixlen;
+  __u16 tcpm_keylen;
+  __be32 tcpm_addr[4];
   __u8 tcpm_key[TCP_MD5SIG_MAXKEYLEN];
 };
 #endif
diff --git a/libc/kernel/uapi/linux/tee.h b/libc/kernel/uapi/linux/tee.h
index 9a42337..20d0d80 100644
--- a/libc/kernel/uapi/linux/tee.h
+++ b/libc/kernel/uapi/linux/tee.h
@@ -26,6 +26,7 @@
 #define TEE_IOCTL_SHM_DMA_BUF 0x2
 #define TEE_MAX_ARG_SIZE 1024
 #define TEE_GEN_CAP_GP (1 << 0)
+#define TEE_GEN_CAP_PRIVILEGED (1 << 1)
 #define TEE_IMPL_ID_OPTEE 1
 #define TEE_OPTEE_CAP_TZ (1 << 0)
 struct tee_ioctl_version_data {
diff --git a/libc/kernel/uapi/linux/tls.h b/libc/kernel/uapi/linux/tls.h
new file mode 100644
index 0000000..73618e0
--- /dev/null
+++ b/libc/kernel/uapi/linux/tls.h
@@ -0,0 +1,51 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ***   To edit the content of this header, modify the corresponding
+ ***   source file (e.g. under external/kernel-headers/original/) then
+ ***   run bionic/libc/kernel/tools/update_all.py
+ ***
+ ***   Any manual change here will be lost the next time this script will
+ ***   be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _UAPI_LINUX_TLS_H
+#define _UAPI_LINUX_TLS_H
+#include <linux/types.h>
+#include <asm/byteorder.h>
+#include <linux/socket.h>
+#include <linux/tcp.h>
+#include <net/tcp.h>
+#define TLS_TX 1
+#define TLS_VERSION_MINOR(ver) ((ver) & 0xFF)
+#define TLS_VERSION_MAJOR(ver) (((ver) >> 8) & 0xFF)
+#define TLS_VERSION_NUMBER(id) ((((id ##_VERSION_MAJOR) & 0xFF) << 8) | ((id ##_VERSION_MINOR) & 0xFF))
+#define TLS_1_2_VERSION_MAJOR 0x3
+#define TLS_1_2_VERSION_MINOR 0x3
+#define TLS_1_2_VERSION TLS_VERSION_NUMBER(TLS_1_2)
+#define TLS_CIPHER_AES_GCM_128 51
+#define TLS_CIPHER_AES_GCM_128_IV_SIZE 8
+#define TLS_CIPHER_AES_GCM_128_KEY_SIZE 16
+#define TLS_CIPHER_AES_GCM_128_SALT_SIZE 4
+#define TLS_CIPHER_AES_GCM_128_TAG_SIZE 16
+#define TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE 8
+#define TLS_SET_RECORD_TYPE 1
+struct tls_crypto_info {
+  __u16 version;
+  __u16 cipher_type;
+};
+struct tls12_crypto_info_aes_gcm_128 {
+  struct tls_crypto_info info;
+  unsigned char iv[TLS_CIPHER_AES_GCM_128_IV_SIZE];
+  unsigned char key[TLS_CIPHER_AES_GCM_128_KEY_SIZE];
+  unsigned char salt[TLS_CIPHER_AES_GCM_128_SALT_SIZE];
+  unsigned char rec_seq[TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE];
+};
+#endif
diff --git a/libc/kernel/uapi/linux/tty.h b/libc/kernel/uapi/linux/tty.h
index 9a09303..48fa908 100644
--- a/libc/kernel/uapi/linux/tty.h
+++ b/libc/kernel/uapi/linux/tty.h
@@ -45,4 +45,6 @@
 #define N_TRACESINK 23
 #define N_TRACEROUTER 24
 #define N_NCI 25
+#define N_SPEAKUP 26
+#define N_NULL 27
 #endif
diff --git a/libc/kernel/uapi/linux/usb/audio.h b/libc/kernel/uapi/linux/usb/audio.h
index 7f961fc..121c859 100644
--- a/libc/kernel/uapi/linux/usb/audio.h
+++ b/libc/kernel/uapi/linux/usb/audio.h
@@ -186,7 +186,7 @@
   __u8 bDescriptorType;
   __u8 bDescriptorSubtype;
   __u8 bUnitID;
-  __u16 wProcessType;
+  __le16 wProcessType;
   __u8 bNrInPins;
   __u8 baSourceID[];
 } __attribute__((packed));
@@ -260,8 +260,8 @@
   __u8 bDescriptorType;
   __u8 bDescriptorSubtype;
   __u8 bFormatType;
-  __u16 wMaxBitRate;
-  __u16 wSamplesPerFrame;
+  __le16 wMaxBitRate;
+  __le16 wSamplesPerFrame;
   __u8 bHeaderLength;
   __u8 bSideBandProtocol;
 } __attribute__((packed));
diff --git a/libc/kernel/uapi/linux/usb/ch9.h b/libc/kernel/uapi/linux/usb/ch9.h
index f06a970..38e7ae7 100644
--- a/libc/kernel/uapi/linux/usb/ch9.h
+++ b/libc/kernel/uapi/linux/usb/ch9.h
@@ -305,6 +305,7 @@
   __u8 bFunctionProtocol;
   __u8 iFunction;
 } __attribute__((packed));
+#define USB_DT_INTERFACE_ASSOCIATION_SIZE 8
 struct usb_security_descriptor {
   __u8 bLength;
   __u8 bDescriptorType;
diff --git a/libc/kernel/uapi/linux/wil6210_uapi.h b/libc/kernel/uapi/linux/usb/charger.h
similarity index 62%
rename from libc/kernel/uapi/linux/wil6210_uapi.h
rename to libc/kernel/uapi/linux/usb/charger.h
index e68b6c8..0810aab 100644
--- a/libc/kernel/uapi/linux/wil6210_uapi.h
+++ b/libc/kernel/uapi/linux/usb/charger.h
@@ -16,30 +16,18 @@
  ***
  ****************************************************************************
  ****************************************************************************/
-#ifndef __WIL6210_UAPI_H__
-#define __WIL6210_UAPI_H__
-#define __user
-#include <linux/sockios.h>
-#define WIL_IOCTL_MEMIO (SIOCDEVPRIVATE + 2)
-#define WIL_IOCTL_MEMIO_BLOCK (SIOCDEVPRIVATE + 3)
-enum wil_memio_op {
-  wil_mmio_read = 0,
-  wil_mmio_write = 1,
-  wil_mmio_op_mask = 0xff,
-  wil_mmio_addr_linker = 0 << 8,
-  wil_mmio_addr_ahb = 1 << 8,
-  wil_mmio_addr_bar = 2 << 8,
-  wil_mmio_addr_mask = 0xff00,
+#ifndef _UAPI__LINUX_USB_CHARGER_H
+#define _UAPI__LINUX_USB_CHARGER_H
+enum usb_charger_type {
+  UNKNOWN_TYPE,
+  SDP_TYPE,
+  DCP_TYPE,
+  CDP_TYPE,
+  ACA_TYPE,
 };
-struct wil_memio {
-  uint32_t op;
-  uint32_t addr;
-  uint32_t val;
-};
-struct wil_memio_block {
-  uint32_t op;
-  uint32_t addr;
-  uint32_t size;
-  void __user * block;
+enum usb_charger_state {
+  USB_CHARGER_DEFAULT,
+  USB_CHARGER_PRESENT,
+  USB_CHARGER_ABSENT,
 };
 #endif
diff --git a/libc/kernel/uapi/linux/usbdevice_fs.h b/libc/kernel/uapi/linux/usbdevice_fs.h
index 76b5f68..87afabe 100644
--- a/libc/kernel/uapi/linux/usbdevice_fs.h
+++ b/libc/kernel/uapi/linux/usbdevice_fs.h
@@ -147,4 +147,5 @@
 #define USBDEVFS_ALLOC_STREAMS _IOR('U', 28, struct usbdevfs_streams)
 #define USBDEVFS_FREE_STREAMS _IOR('U', 29, struct usbdevfs_streams)
 #define USBDEVFS_DROP_PRIVILEGES _IOW('U', 30, __u32)
+#define USBDEVFS_GET_SPEED _IO('U', 31)
 #endif
diff --git a/libc/kernel/uapi/linux/userfaultfd.h b/libc/kernel/uapi/linux/userfaultfd.h
index caa1eb4..ecc6302 100644
--- a/libc/kernel/uapi/linux/userfaultfd.h
+++ b/libc/kernel/uapi/linux/userfaultfd.h
@@ -20,7 +20,7 @@
 #define _LINUX_USERFAULTFD_H
 #include <linux/types.h>
 #define UFFD_API ((__u64) 0xAA)
-#define UFFD_API_FEATURES (UFFD_FEATURE_EVENT_FORK | UFFD_FEATURE_EVENT_REMAP | UFFD_FEATURE_EVENT_REMOVE | UFFD_FEATURE_EVENT_UNMAP | UFFD_FEATURE_MISSING_HUGETLBFS | UFFD_FEATURE_MISSING_SHMEM)
+#define UFFD_API_FEATURES (UFFD_FEATURE_EVENT_FORK | UFFD_FEATURE_EVENT_REMAP | UFFD_FEATURE_EVENT_REMOVE | UFFD_FEATURE_EVENT_UNMAP | UFFD_FEATURE_MISSING_HUGETLBFS | UFFD_FEATURE_MISSING_SHMEM | UFFD_FEATURE_SIGBUS | UFFD_FEATURE_THREAD_ID)
 #define UFFD_API_IOCTLS ((__u64) 1 << _UFFDIO_REGISTER | (__u64) 1 << _UFFDIO_UNREGISTER | (__u64) 1 << _UFFDIO_API)
 #define UFFD_API_RANGE_IOCTLS ((__u64) 1 << _UFFDIO_WAKE | (__u64) 1 << _UFFDIO_COPY | (__u64) 1 << _UFFDIO_ZEROPAGE)
 #define UFFD_API_RANGE_IOCTLS_BASIC ((__u64) 1 << _UFFDIO_WAKE | (__u64) 1 << _UFFDIO_COPY)
@@ -46,6 +46,9 @@
     struct {
       __u64 flags;
       __u64 address;
+      union {
+        __u32 ptid;
+      } feat;
     } pagefault;
     struct {
       __u32 ufd;
@@ -82,6 +85,8 @@
 #define UFFD_FEATURE_MISSING_HUGETLBFS (1 << 4)
 #define UFFD_FEATURE_MISSING_SHMEM (1 << 5)
 #define UFFD_FEATURE_EVENT_UNMAP (1 << 6)
+#define UFFD_FEATURE_SIGBUS (1 << 7)
+#define UFFD_FEATURE_THREAD_ID (1 << 8)
   __u64 features;
   __u64 ioctls;
 };
diff --git a/libc/kernel/uapi/linux/uuid.h b/libc/kernel/uapi/linux/uuid.h
index c48b6d3..808578f 100644
--- a/libc/kernel/uapi/linux/uuid.h
+++ b/libc/kernel/uapi/linux/uuid.h
@@ -22,16 +22,11 @@
 #include <linux/string.h>
 typedef struct {
   __u8 b[16];
-} uuid_le;
-typedef struct {
-  __u8 b[16];
-} uuid_be;
-#define UUID_LE(a,b,c,d0,d1,d2,d3,d4,d5,d6,d7) \
-((uuid_le) \
+} guid_t;
+#define GUID_INIT(a,b,c,d0,d1,d2,d3,d4,d5,d6,d7) \
+((guid_t) \
 { { (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, (b) & 0xff, ((b) >> 8) & 0xff, (c) & 0xff, ((c) >> 8) & 0xff, (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) } })
-#define UUID_BE(a,b,c,d0,d1,d2,d3,d4,d5,d6,d7) \
-((uuid_be) \
-{ { ((a) >> 24) & 0xff, ((a) >> 16) & 0xff, ((a) >> 8) & 0xff, (a) & 0xff, ((b) >> 8) & 0xff, (b) & 0xff, ((c) >> 8) & 0xff, (c) & 0xff, (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) } })
+typedef guid_t uuid_le;
+#define UUID_LE(a,b,c,d0,d1,d2,d3,d4,d5,d6,d7) GUID_INIT(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7)
 #define NULL_UUID_LE UUID_LE(0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)
-#define NULL_UUID_BE UUID_BE(0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)
 #endif
diff --git a/libc/kernel/uapi/linux/v4l2-controls.h b/libc/kernel/uapi/linux/v4l2-controls.h
index 8b69770..302da8f 100644
--- a/libc/kernel/uapi/linux/v4l2-controls.h
+++ b/libc/kernel/uapi/linux/v4l2-controls.h
@@ -107,6 +107,8 @@
 #define V4L2_CID_USER_SAA7134_BASE (V4L2_CID_USER_BASE + 0x1060)
 #define V4L2_CID_USER_ADV7180_BASE (V4L2_CID_USER_BASE + 0x1070)
 #define V4L2_CID_USER_TC358743_BASE (V4L2_CID_USER_BASE + 0x1080)
+#define V4L2_CID_USER_MAX217X_BASE (V4L2_CID_USER_BASE + 0x1090)
+#define V4L2_CID_USER_IMX_BASE (V4L2_CID_USER_BASE + 0x1090)
 #define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900)
 #define V4L2_CID_MPEG_CLASS (V4L2_CTRL_CLASS_MPEG | 1)
 #define V4L2_CID_MPEG_STREAM_TYPE (V4L2_CID_MPEG_BASE + 0)
@@ -744,6 +746,7 @@
 #define V4L2_CID_PIXEL_RATE (V4L2_CID_IMAGE_PROC_CLASS_BASE + 2)
 #define V4L2_CID_TEST_PATTERN (V4L2_CID_IMAGE_PROC_CLASS_BASE + 3)
 #define V4L2_CID_DEINTERLACING_MODE (V4L2_CID_IMAGE_PROC_CLASS_BASE + 4)
+#define V4L2_CID_DIGITAL_GAIN (V4L2_CID_IMAGE_PROC_CLASS_BASE + 5)
 #define V4L2_CID_DV_CLASS_BASE (V4L2_CTRL_CLASS_DV | 0x900)
 #define V4L2_CID_DV_CLASS (V4L2_CTRL_CLASS_DV | 1)
 #define V4L2_CID_DV_TX_HOTPLUG (V4L2_CID_DV_CLASS_BASE + 1)
diff --git a/libc/kernel/uapi/linux/version.h b/libc/kernel/uapi/linux/version.h
index 73eb988..7714cb7 100644
--- a/libc/kernel/uapi/linux/version.h
+++ b/libc/kernel/uapi/linux/version.h
@@ -16,5 +16,5 @@
  ***
  ****************************************************************************
  ****************************************************************************/
-#define LINUX_VERSION_CODE 265219
+#define LINUX_VERSION_CODE 265728
 #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
diff --git a/libc/kernel/uapi/linux/videodev2.h b/libc/kernel/uapi/linux/videodev2.h
index 25e2fe8..c350108 100644
--- a/libc/kernel/uapi/linux/videodev2.h
+++ b/libc/kernel/uapi/linux/videodev2.h
@@ -288,6 +288,10 @@
 #define V4L2_PIX_FMT_SGBRG12 v4l2_fourcc('G', 'B', '1', '2')
 #define V4L2_PIX_FMT_SGRBG12 v4l2_fourcc('B', 'A', '1', '2')
 #define V4L2_PIX_FMT_SRGGB12 v4l2_fourcc('R', 'G', '1', '2')
+#define V4L2_PIX_FMT_SBGGR12P v4l2_fourcc('p', 'B', 'C', 'C')
+#define V4L2_PIX_FMT_SGBRG12P v4l2_fourcc('p', 'G', 'C', 'C')
+#define V4L2_PIX_FMT_SGRBG12P v4l2_fourcc('p', 'g', 'C', 'C')
+#define V4L2_PIX_FMT_SRGGB12P v4l2_fourcc('p', 'R', 'C', 'C')
 #define V4L2_PIX_FMT_SBGGR16 v4l2_fourcc('B', 'Y', 'R', '2')
 #define V4L2_PIX_FMT_SGBRG16 v4l2_fourcc('G', 'B', '1', '6')
 #define V4L2_PIX_FMT_SGRBG16 v4l2_fourcc('G', 'R', '1', '6')
@@ -346,6 +350,9 @@
 #define V4L2_SDR_FMT_CS8 v4l2_fourcc('C', 'S', '0', '8')
 #define V4L2_SDR_FMT_CS14LE v4l2_fourcc('C', 'S', '1', '4')
 #define V4L2_SDR_FMT_RU12LE v4l2_fourcc('R', 'U', '1', '2')
+#define V4L2_SDR_FMT_PCU16BE v4l2_fourcc('P', 'C', '1', '6')
+#define V4L2_SDR_FMT_PCU18BE v4l2_fourcc('P', 'C', '1', '8')
+#define V4L2_SDR_FMT_PCU20BE v4l2_fourcc('P', 'C', '2', '0')
 #define V4L2_TCH_FMT_DELTA_TD16 v4l2_fourcc('T', 'D', '1', '6')
 #define V4L2_TCH_FMT_DELTA_TD08 v4l2_fourcc('T', 'D', '0', '8')
 #define V4L2_TCH_FMT_TU16 v4l2_fourcc('T', 'U', '1', '6')
diff --git a/libc/kernel/uapi/linux/vtpm_proxy.h b/libc/kernel/uapi/linux/vtpm_proxy.h
index 15e39f2..0ab0536 100644
--- a/libc/kernel/uapi/linux/vtpm_proxy.h
+++ b/libc/kernel/uapi/linux/vtpm_proxy.h
@@ -31,4 +31,6 @@
   __u32 minor;
 };
 #define VTPM_PROXY_IOC_NEW_DEV _IOWR(0xa1, 0x00, struct vtpm_proxy_new_dev)
+#define TPM2_CC_SET_LOCALITY 0x20001000
+#define TPM_ORD_SET_LOCALITY 0x20001000
 #endif
diff --git a/libc/kernel/uapi/linux/xfrm.h b/libc/kernel/uapi/linux/xfrm.h
index 4ff9bea..5ec7193 100644
--- a/libc/kernel/uapi/linux/xfrm.h
+++ b/libc/kernel/uapi/linux/xfrm.h
@@ -258,6 +258,7 @@
   XFRMA_ADDRESS_FILTER,
   XFRMA_PAD,
   XFRMA_OFFLOAD_DEV,
+  XFRMA_OUTPUT_MARK,
   __XFRMA_MAX
 #define XFRMA_MAX (__XFRMA_MAX - 1)
 };
diff --git a/libc/kernel/uapi/rdma/ib_user_ioctl_verbs.h b/libc/kernel/uapi/rdma/ib_user_ioctl_verbs.h
new file mode 100644
index 0000000..766fe4c
--- /dev/null
+++ b/libc/kernel/uapi/rdma/ib_user_ioctl_verbs.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ***   To edit the content of this header, modify the corresponding
+ ***   source file (e.g. under external/kernel-headers/original/) then
+ ***   run bionic/libc/kernel/tools/update_all.py
+ ***
+ ***   Any manual change here will be lost the next time this script will
+ ***   be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef IB_USER_IOCTL_VERBS_H
+#define IB_USER_IOCTL_VERBS_H
+#include <rdma/rdma_user_ioctl.h>
+#define UVERBS_UDATA_DRIVER_DATA_NS 1
+#define UVERBS_UDATA_DRIVER_DATA_FLAG (1UL << UVERBS_ID_NS_SHIFT)
+enum uverbs_default_objects {
+  UVERBS_OBJECT_DEVICE,
+  UVERBS_OBJECT_PD,
+  UVERBS_OBJECT_COMP_CHANNEL,
+  UVERBS_OBJECT_CQ,
+  UVERBS_OBJECT_QP,
+  UVERBS_OBJECT_SRQ,
+  UVERBS_OBJECT_AH,
+  UVERBS_OBJECT_MR,
+  UVERBS_OBJECT_MW,
+  UVERBS_OBJECT_FLOW,
+  UVERBS_OBJECT_XRCD,
+  UVERBS_OBJECT_RWQ_IND_TBL,
+  UVERBS_OBJECT_WQ,
+  UVERBS_OBJECT_LAST,
+};
+enum {
+  UVERBS_UHW_IN = UVERBS_UDATA_DRIVER_DATA_FLAG,
+  UVERBS_UHW_OUT,
+};
+enum uverbs_create_cq_cmd_attr_ids {
+  CREATE_CQ_HANDLE,
+  CREATE_CQ_CQE,
+  CREATE_CQ_USER_HANDLE,
+  CREATE_CQ_COMP_CHANNEL,
+  CREATE_CQ_COMP_VECTOR,
+  CREATE_CQ_FLAGS,
+  CREATE_CQ_RESP_CQE,
+};
+enum uverbs_destroy_cq_cmd_attr_ids {
+  DESTROY_CQ_HANDLE,
+  DESTROY_CQ_RESP,
+};
+enum uverbs_actions_cq_ops {
+  UVERBS_CQ_CREATE,
+  UVERBS_CQ_DESTROY,
+};
+#endif
diff --git a/libc/kernel/uapi/rdma/ib_user_verbs.h b/libc/kernel/uapi/rdma/ib_user_verbs.h
index 4feb031..ff3ebcb 100644
--- a/libc/kernel/uapi/rdma/ib_user_verbs.h
+++ b/libc/kernel/uapi/rdma/ib_user_verbs.h
@@ -174,6 +174,14 @@
   __u32 max_rwq_indirection_table_size;
   __u32 reserved;
 };
+struct ib_uverbs_tm_caps {
+  __u32 max_rndv_hdr_size;
+  __u32 max_num_tags;
+  __u32 flags;
+  __u32 max_ops;
+  __u32 max_sge;
+  __u32 reserved;
+};
 struct ib_uverbs_ex_query_device_resp {
   struct ib_uverbs_query_device_resp base;
   __u32 comp_mask;
@@ -185,6 +193,7 @@
   struct ib_uverbs_rss_caps rss_caps;
   __u32 max_wq_type_rq;
   __u32 raw_packet_caps;
+  struct ib_uverbs_tm_caps tm_caps;
 };
 struct ib_uverbs_query_port {
   __u64 response;
@@ -467,7 +476,7 @@
   __u32 comp_mask;
   __u32 create_flags;
   __u32 rwq_ind_tbl_handle;
-  __u32 reserved1;
+  __u32 source_qpn;
 };
 struct ib_uverbs_open_qp {
   __u64 response;
@@ -852,7 +861,7 @@
   __u32 max_wr;
   __u32 max_sge;
   __u32 srq_limit;
-  __u32 reserved;
+  __u32 max_num_tags;
   __u32 xrcd_handle;
   __u32 cq_handle;
   __u64 driver_data[0];
diff --git a/libc/kernel/uapi/rdma/mlx4-abi.h b/libc/kernel/uapi/rdma/mlx4-abi.h
index 232d835..078b386 100644
--- a/libc/kernel/uapi/rdma/mlx4-abi.h
+++ b/libc/kernel/uapi/rdma/mlx4-abi.h
@@ -56,12 +56,49 @@
   __u32 srqn;
   __u32 reserved;
 };
+struct mlx4_ib_create_qp_rss {
+  __u64 rx_hash_fields_mask;
+  __u8 rx_hash_function;
+  __u8 reserved[7];
+  __u8 rx_hash_key[40];
+  __u32 comp_mask;
+  __u32 reserved1;
+};
 struct mlx4_ib_create_qp {
   __u64 buf_addr;
   __u64 db_addr;
   __u8 log_sq_bb_count;
   __u8 log_sq_stride;
   __u8 sq_no_prefetch;
-  __u8 reserved[5];
+  __u8 reserved;
+  __u32 inl_recv_sz;
+};
+struct mlx4_ib_create_wq {
+  __u64 buf_addr;
+  __u64 db_addr;
+  __u8 log_range_size;
+  __u8 reserved[3];
+  __u32 comp_mask;
+};
+struct mlx4_ib_modify_wq {
+  __u32 comp_mask;
+  __u32 reserved;
+};
+struct mlx4_ib_create_rwq_ind_tbl_resp {
+  __u32 response_length;
+  __u32 reserved;
+};
+enum mlx4_ib_rx_hash_function_flags {
+  MLX4_IB_RX_HASH_FUNC_TOEPLITZ = 1 << 0,
+};
+enum mlx4_ib_rx_hash_fields {
+  MLX4_IB_RX_HASH_SRC_IPV4 = 1 << 0,
+  MLX4_IB_RX_HASH_DST_IPV4 = 1 << 1,
+  MLX4_IB_RX_HASH_SRC_IPV6 = 1 << 2,
+  MLX4_IB_RX_HASH_DST_IPV6 = 1 << 3,
+  MLX4_IB_RX_HASH_SRC_PORT_TCP = 1 << 4,
+  MLX4_IB_RX_HASH_DST_PORT_TCP = 1 << 5,
+  MLX4_IB_RX_HASH_SRC_PORT_UDP = 1 << 6,
+  MLX4_IB_RX_HASH_DST_PORT_UDP = 1 << 7
 };
 #endif
diff --git a/libc/kernel/uapi/rdma/mlx5-abi.h b/libc/kernel/uapi/rdma/mlx5-abi.h
index 6e76a3d..b51ff4e 100644
--- a/libc/kernel/uapi/rdma/mlx5-abi.h
+++ b/libc/kernel/uapi/rdma/mlx5-abi.h
@@ -112,6 +112,20 @@
   __u32 supported_qpts;
   __u32 reserved;
 };
+enum mlx5_ib_mpw_caps {
+  MPW_RESERVED = 1 << 0,
+  MLX5_IB_ALLOW_MPW = 1 << 1,
+  MLX5_IB_SUPPORT_EMPW = 1 << 2,
+};
+enum mlx5_ib_sw_parsing_offloads {
+  MLX5_IB_SW_PARSING = 1 << 0,
+  MLX5_IB_SW_PARSING_CSUM = 1 << 1,
+  MLX5_IB_SW_PARSING_LSO = 1 << 2,
+};
+struct mlx5_ib_sw_parsing_caps {
+  __u32 sw_parsing_offloads;
+  __u32 supported_qpts;
+};
 struct mlx5_ib_query_device_resp {
   __u32 comp_mask;
   __u32 response_length;
@@ -121,6 +135,7 @@
   struct mlx5_packet_pacing_caps packet_pacing_caps;
   __u32 mlx5_ib_support_multi_pkt_send_wqes;
   __u32 reserved;
+  struct mlx5_ib_sw_parsing_caps sw_parsing_caps;
 };
 struct mlx5_ib_create_cq {
   __u64 buf_addr;
diff --git a/libc/kernel/uapi/rdma/qedr-abi.h b/libc/kernel/uapi/rdma/qedr-abi.h
index 597391f..55af44b 100644
--- a/libc/kernel/uapi/rdma/qedr-abi.h
+++ b/libc/kernel/uapi/rdma/qedr-abi.h
@@ -30,6 +30,9 @@
   __u32 sges_per_recv_wr;
   __u32 sges_per_srq_wr;
   __u32 max_cqes;
+  __u8 dpm_enabled;
+  __u8 wids_enabled;
+  __u16 wid_count;
 };
 struct qedr_alloc_pd_ureq {
   __u64 rsvd1;
diff --git a/libc/kernel/uapi/rdma/rdma_netlink.h b/libc/kernel/uapi/rdma/rdma_netlink.h
index ae261d7..c7bcb6d 100644
--- a/libc/kernel/uapi/rdma/rdma_netlink.h
+++ b/libc/kernel/uapi/rdma/rdma_netlink.h
@@ -24,7 +24,7 @@
   RDMA_NL_IWCM,
   RDMA_NL_RSVD,
   RDMA_NL_LS,
-  RDMA_NL_I40IW,
+  RDMA_NL_NLDEV,
   RDMA_NL_NUM_CLIENTS
 };
 enum {
@@ -170,4 +170,34 @@
 struct rdma_nla_ls_gid {
   __u8 gid[16];
 };
+enum rdma_nldev_command {
+  RDMA_NLDEV_CMD_UNSPEC,
+  RDMA_NLDEV_CMD_GET,
+  RDMA_NLDEV_CMD_SET,
+  RDMA_NLDEV_CMD_NEW,
+  RDMA_NLDEV_CMD_DEL,
+  RDMA_NLDEV_CMD_PORT_GET,
+  RDMA_NLDEV_CMD_PORT_SET,
+  RDMA_NLDEV_CMD_PORT_NEW,
+  RDMA_NLDEV_CMD_PORT_DEL,
+  RDMA_NLDEV_NUM_OPS
+};
+enum rdma_nldev_attr {
+  RDMA_NLDEV_ATTR_UNSPEC,
+  RDMA_NLDEV_ATTR_DEV_INDEX,
+  RDMA_NLDEV_ATTR_DEV_NAME,
+  RDMA_NLDEV_ATTR_PORT_INDEX,
+  RDMA_NLDEV_ATTR_CAP_FLAGS,
+  RDMA_NLDEV_ATTR_FW_VERSION,
+  RDMA_NLDEV_ATTR_NODE_GUID,
+  RDMA_NLDEV_ATTR_SYS_IMAGE_GUID,
+  RDMA_NLDEV_ATTR_SUBNET_PREFIX,
+  RDMA_NLDEV_ATTR_LID,
+  RDMA_NLDEV_ATTR_SM_LID,
+  RDMA_NLDEV_ATTR_LMC,
+  RDMA_NLDEV_ATTR_PORT_STATE,
+  RDMA_NLDEV_ATTR_PORT_PHYS_STATE,
+  RDMA_NLDEV_ATTR_DEV_NODE_TYPE,
+  RDMA_NLDEV_ATTR_MAX
+};
 #endif
diff --git a/libc/kernel/uapi/rdma/rdma_user_ioctl.h b/libc/kernel/uapi/rdma/rdma_user_ioctl.h
index bb65c5d..41c11bc 100644
--- a/libc/kernel/uapi/rdma/rdma_user_ioctl.h
+++ b/libc/kernel/uapi/rdma/rdma_user_ioctl.h
@@ -24,6 +24,28 @@
 #include <rdma/hfi/hfi1_ioctl.h>
 #define RDMA_IOCTL_MAGIC 0x1b
 #define IB_IOCTL_MAGIC RDMA_IOCTL_MAGIC
+#define RDMA_VERBS_IOCTL _IOWR(RDMA_IOCTL_MAGIC, 1, struct ib_uverbs_ioctl_hdr)
+#define UVERBS_ID_NS_MASK 0xF000
+#define UVERBS_ID_NS_SHIFT 12
+enum {
+  UVERBS_ATTR_F_MANDATORY = 1U << 0,
+  UVERBS_ATTR_F_VALID_OUTPUT = 1U << 1,
+};
+struct ib_uverbs_attr {
+  __u16 attr_id;
+  __u16 len;
+  __u16 flags;
+  __u16 reserved;
+  __u64 data;
+};
+struct ib_uverbs_ioctl_hdr {
+  __u16 length;
+  __u16 object_id;
+  __u16 method_id;
+  __u16 num_attrs;
+  __u64 reserved;
+  struct ib_uverbs_attr attrs[0];
+};
 #define IB_USER_MAD_REGISTER_AGENT _IOWR(RDMA_IOCTL_MAGIC, 0x01, struct ib_user_mad_reg_req)
 #define IB_USER_MAD_UNREGISTER_AGENT _IOW(RDMA_IOCTL_MAGIC, 0x02, __u32)
 #define IB_USER_MAD_ENABLE_PKEY _IO(RDMA_IOCTL_MAGIC, 0x03)
diff --git a/libc/kernel/uapi/rdma/vmw_pvrdma-abi.h b/libc/kernel/uapi/rdma/vmw_pvrdma-abi.h
index 3666815..2062366 100644
--- a/libc/kernel/uapi/rdma/vmw_pvrdma-abi.h
+++ b/libc/kernel/uapi/rdma/vmw_pvrdma-abi.h
@@ -92,7 +92,8 @@
   PVRDMA_WC_IP_CSUM_OK = 1 << 3,
   PVRDMA_WC_WITH_SMAC = 1 << 4,
   PVRDMA_WC_WITH_VLAN = 1 << 5,
-  PVRDMA_WC_FLAGS_MAX = PVRDMA_WC_WITH_VLAN,
+  PVRDMA_WC_WITH_NETWORK_HDR_TYPE = 1 << 6,
+  PVRDMA_WC_FLAGS_MAX = PVRDMA_WC_WITH_NETWORK_HDR_TYPE,
 };
 struct pvrdma_alloc_ucontext_resp {
   __u32 qp_tab_size;
@@ -226,6 +227,7 @@
   __u8 dlid_path_bits;
   __u8 port_num;
   __u8 smac[6];
-  __u8 reserved2[7];
+  __u8 network_hdr_type;
+  __u8 reserved2[6];
 };
 #endif
diff --git a/libc/kernel/uapi/scsi/cxlflash_ioctl.h b/libc/kernel/uapi/scsi/cxlflash_ioctl.h
index 91ffe62..9781905 100644
--- a/libc/kernel/uapi/scsi/cxlflash_ioctl.h
+++ b/libc/kernel/uapi/scsi/cxlflash_ioctl.h
@@ -19,6 +19,7 @@
 #ifndef _CXLFLASH_IOCTL_H
 #define _CXLFLASH_IOCTL_H
 #include <linux/types.h>
+#define CXLFLASH_WWID_LEN 16
 #define DK_CXLFLASH_VERSION_0 0
 struct dk_cxlflash_hdr {
   __u16 version;
@@ -104,7 +105,7 @@
   __u64 adap_fd;
   __u64 reserved[8];
 };
-#define DK_CXLFLASH_MANAGE_LUN_WWID_LEN 16
+#define DK_CXLFLASH_MANAGE_LUN_WWID_LEN CXLFLASH_WWID_LEN
 #define DK_CXLFLASH_MANAGE_LUN_ENABLE_SUPERPIPE 0x8000000000000000ULL
 #define DK_CXLFLASH_MANAGE_LUN_DISABLE_SUPERPIPE 0x4000000000000000ULL
 #define DK_CXLFLASH_MANAGE_LUN_ALL_PORTS_ACCESSIBLE 0x2000000000000000ULL
@@ -138,4 +139,48 @@
 #define DK_CXLFLASH_USER_VIRTUAL CXL_IOWR(0x87, dk_cxlflash_uvirtual)
 #define DK_CXLFLASH_VLUN_RESIZE CXL_IOWR(0x88, dk_cxlflash_resize)
 #define DK_CXLFLASH_VLUN_CLONE CXL_IOWR(0x89, dk_cxlflash_clone)
+#define HT_CXLFLASH_VERSION_0 0
+struct ht_cxlflash_hdr {
+  __u16 version;
+  __u16 subcmd;
+  __u16 rsvd[2];
+  __u64 flags;
+  __u64 return_flags;
+};
+#define HT_CXLFLASH_HOST_READ 0x0000000000000000ULL
+#define HT_CXLFLASH_HOST_WRITE 0x0000000000000001ULL
+#define HT_CXLFLASH_LUN_PROVISION_SUBCMD_CREATE_LUN 0x0001
+#define HT_CXLFLASH_LUN_PROVISION_SUBCMD_DELETE_LUN 0x0002
+#define HT_CXLFLASH_LUN_PROVISION_SUBCMD_QUERY_PORT 0x0003
+struct ht_cxlflash_lun_provision {
+  struct ht_cxlflash_hdr hdr;
+  __u16 port;
+  __u16 reserved16[3];
+  __u64 size;
+  __u64 lun_id;
+  __u8 wwid[CXLFLASH_WWID_LEN];
+  __u64 max_num_luns;
+  __u64 cur_num_luns;
+  __u64 max_cap_port;
+  __u64 cur_cap_port;
+  __u64 reserved[8];
+};
+#define HT_CXLFLASH_AFU_DEBUG_MAX_DATA_LEN 262144
+#define HT_CXLFLASH_AFU_DEBUG_SUBCMD_LEN 12
+struct ht_cxlflash_afu_debug {
+  struct ht_cxlflash_hdr hdr;
+  __u8 reserved8[4];
+  __u8 afu_subcmd[HT_CXLFLASH_AFU_DEBUG_SUBCMD_LEN];
+  __u64 data_ea;
+  __u32 data_len;
+  __u32 reserved32;
+  __u64 reserved[8];
+};
+union cxlflash_ht_ioctls {
+  struct ht_cxlflash_lun_provision lun_provision;
+  struct ht_cxlflash_afu_debug afu_debug;
+};
+#define MAX_HT_CXLFLASH_IOCTL_SZ (sizeof(union cxlflash_ht_ioctls))
+#define HT_CXLFLASH_LUN_PROVISION CXL_IOWR(0xBF, ht_cxlflash_lun_provision)
+#define HT_CXLFLASH_AFU_DEBUG CXL_IOWR(0xBE, ht_cxlflash_afu_debug)
 #endif
diff --git a/libc/kernel/uapi/sound/asoc.h b/libc/kernel/uapi/sound/asoc.h
index 35e1b15..d0bab8b 100644
--- a/libc/kernel/uapi/sound/asoc.h
+++ b/libc/kernel/uapi/sound/asoc.h
@@ -53,7 +53,15 @@
 #define SND_SOC_TPLG_DAPM_DAI_IN 13
 #define SND_SOC_TPLG_DAPM_DAI_OUT 14
 #define SND_SOC_TPLG_DAPM_DAI_LINK 15
-#define SND_SOC_TPLG_DAPM_LAST SND_SOC_TPLG_DAPM_DAI_LINK
+#define SND_SOC_TPLG_DAPM_BUFFER 16
+#define SND_SOC_TPLG_DAPM_SCHEDULER 17
+#define SND_SOC_TPLG_DAPM_EFFECT 18
+#define SND_SOC_TPLG_DAPM_SIGGEN 19
+#define SND_SOC_TPLG_DAPM_SRC 20
+#define SND_SOC_TPLG_DAPM_ASRC 21
+#define SND_SOC_TPLG_DAPM_ENCODER 22
+#define SND_SOC_TPLG_DAPM_DECODER 23
+#define SND_SOC_TPLG_DAPM_LAST SND_SOC_TPLG_DAPM_DECODER
 #define SND_SOC_TPLG_MAGIC 0x41536F43
 #define SND_SOC_TPLG_NUM_TEXTS 16
 #define SND_SOC_TPLG_ABI_VERSION 0x5
diff --git a/libc/kernel/uapi/sound/asound.h b/libc/kernel/uapi/sound/asound.h
index e3041ce..63f66b4 100644
--- a/libc/kernel/uapi/sound/asound.h
+++ b/libc/kernel/uapi/sound/asound.h
@@ -100,7 +100,7 @@
 #define SNDRV_HWDEP_IOCTL_INFO _IOR('H', 0x01, struct snd_hwdep_info)
 #define SNDRV_HWDEP_IOCTL_DSP_STATUS _IOR('H', 0x02, struct snd_hwdep_dsp_status)
 #define SNDRV_HWDEP_IOCTL_DSP_LOAD _IOW('H', 0x03, struct snd_hwdep_dsp_image)
-#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 13)
+#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 14)
 typedef unsigned long snd_pcm_uframes_t;
 typedef signed long snd_pcm_sframes_t;
 enum {
@@ -205,6 +205,7 @@
 #define SNDRV_PCM_INFO_MMAP_VALID 0x00000002
 #define SNDRV_PCM_INFO_DOUBLE 0x00000004
 #define SNDRV_PCM_INFO_BATCH 0x00000010
+#define SNDRV_PCM_INFO_SYNC_APPLPTR 0x00000020
 #define SNDRV_PCM_INFO_INTERLEAVED 0x00000100
 #define SNDRV_PCM_INFO_NONINTERLEAVED 0x00000200
 #define SNDRV_PCM_INFO_COMPLEX 0x00000400
@@ -446,6 +447,7 @@
 #define SNDRV_PCM_IOCTL_INFO _IOR('A', 0x01, struct snd_pcm_info)
 #define SNDRV_PCM_IOCTL_TSTAMP _IOW('A', 0x02, int)
 #define SNDRV_PCM_IOCTL_TTSTAMP _IOW('A', 0x03, int)
+#define SNDRV_PCM_IOCTL_USER_PVERSION _IOW('A', 0x04, int)
 #define SNDRV_PCM_IOCTL_HW_REFINE _IOWR('A', 0x10, struct snd_pcm_hw_params)
 #define SNDRV_PCM_IOCTL_HW_PARAMS _IOWR('A', 0x11, struct snd_pcm_hw_params)
 #define SNDRV_PCM_IOCTL_HW_FREE _IO('A', 0x12)
diff --git a/libc/kernel/uapi/sound/snd_sst_tokens.h b/libc/kernel/uapi/sound/snd_sst_tokens.h
index 13ae705..a4cfdd5 100644
--- a/libc/kernel/uapi/sound/snd_sst_tokens.h
+++ b/libc/kernel/uapi/sound/snd_sst_tokens.h
@@ -68,6 +68,31 @@
   SKL_TKN_STR_LIB_NAME,
   SKL_TKN_U32_PMODE,
   SKL_TKL_U32_D0I3_CAPS,
-  SKL_TKN_MAX = SKL_TKL_U32_D0I3_CAPS,
+  SKL_TKN_U32_D0I3_CAPS = SKL_TKL_U32_D0I3_CAPS,
+  SKL_TKN_U32_DMA_BUF_SIZE,
+  SKL_TKN_U32_PIPE_DIRECTION,
+  SKL_TKN_U32_PIPE_CONFIG_ID,
+  SKL_TKN_U32_NUM_CONFIGS,
+  SKL_TKN_U32_PATH_MEM_PGS,
+  SKL_TKN_U32_CFG_FREQ,
+  SKL_TKN_U8_CFG_CHAN,
+  SKL_TKN_U8_CFG_BPS,
+  SKL_TKN_CFG_MOD_RES_ID,
+  SKL_TKN_CFG_MOD_FMT_ID,
+  SKL_TKN_U8_NUM_MOD,
+  SKL_TKN_MM_U8_MOD_IDX,
+  SKL_TKN_MM_U8_NUM_RES,
+  SKL_TKN_MM_U8_NUM_INTF,
+  SKL_TKN_MM_U32_RES_ID,
+  SKL_TKN_MM_U32_CPS,
+  SKL_TKN_MM_U32_DMA_SIZE,
+  SKL_TKN_MM_U32_CPC,
+  SKL_TKN_MM_U32_RES_PIN_ID,
+  SKL_TKN_MM_U32_INTF_PIN_ID,
+  SKL_TKN_MM_U32_PIN_BUF,
+  SKL_TKN_MM_U32_FMT_ID,
+  SKL_TKN_MM_U32_NUM_IN_FMT,
+  SKL_TKN_MM_U32_NUM_OUT_FMT,
+  SKL_TKN_MAX = SKL_TKN_MM_U32_NUM_OUT_FMT,
 };
 #endif
diff --git a/libc/private/bionic_macros.h b/libc/private/bionic_macros.h
index a3a3ece..979a704 100644
--- a/libc/private/bionic_macros.h
+++ b/libc/private/bionic_macros.h
@@ -78,4 +78,20 @@
 #define BIONIC_STOP_UNWIND asm volatile(".cfi_undefined $ra")
 #endif
 
+// The arraysize(arr) macro returns the # of elements in an array arr.
+// The expression is a compile-time constant, and therefore can be
+// used in defining new arrays, for example.  If you use arraysize on
+// a pointer by mistake, you will get a compile-time error.
+//
+// One caveat is that arraysize() doesn't accept any array of an
+// anonymous type or a type defined inside a function.
+//
+// This template function declaration is used in defining arraysize.
+// Note that the function doesn't need an implementation, as we only
+// use its type.
+template <typename T, size_t N>
+char (&ArraySizeHelper(T (&array)[N]))[N];  // NOLINT(readability/casting)
+
+#define arraysize(array) (sizeof(ArraySizeHelper(array)))
+
 #endif // _BIONIC_MACROS_H_
diff --git a/libc/system_properties/context_node.cpp b/libc/system_properties/context_node.cpp
new file mode 100644
index 0000000..13cef75
--- /dev/null
+++ b/libc/system_properties/context_node.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "context_node.h"
+
+#include <unistd.h>
+
+#include <async_safe/log.h>
+
+#include "property_filename.h"
+
+// pthread_mutex_lock() calls into system_properties in the case of contention.
+// This creates a risk of dead lock if any system_properties functions
+// use pthread locks after system_property initialization.
+//
+// For this reason, the below three functions use a bionic Lock and static
+// allocation of memory for each filename.
+
+bool ContextNode::Open(bool access_rw, bool* fsetxattr_failed) {
+  lock_.lock();
+  if (pa_) {
+    lock_.unlock();
+    return true;
+  }
+
+  char filename[PROP_FILENAME_MAX];
+  int len =
+      async_safe_format_buffer(filename, sizeof(filename), "%s/%s", property_filename, context_);
+  if (len < 0 || len > PROP_FILENAME_MAX) {
+    lock_.unlock();
+    return false;
+  }
+
+  if (access_rw) {
+    pa_ = prop_area::map_prop_area_rw(filename, context_, fsetxattr_failed);
+  } else {
+    pa_ = prop_area::map_prop_area(filename);
+  }
+  lock_.unlock();
+  return pa_;
+}
+
+bool ContextNode::CheckAccessAndOpen() {
+  if (!pa_ && !no_access_) {
+    if (!CheckAccess() || !Open(false, nullptr)) {
+      no_access_ = true;
+    }
+  }
+  return pa_;
+}
+
+void ContextNode::ResetAccess() {
+  if (!CheckAccess()) {
+    Unmap();
+    no_access_ = true;
+  } else {
+    no_access_ = false;
+  }
+}
+
+bool ContextNode::CheckAccess() {
+  char filename[PROP_FILENAME_MAX];
+  int len =
+      async_safe_format_buffer(filename, sizeof(filename), "%s/%s", property_filename, context_);
+  if (len < 0 || len > PROP_FILENAME_MAX) {
+    return false;
+  }
+
+  return access(filename, R_OK) == 0;
+}
+
+void ContextNode::Unmap() {
+  prop_area::unmap_prop_area(&pa_);
+}
diff --git a/libc/system_properties/context_node.h b/libc/system_properties/context_node.h
new file mode 100644
index 0000000..1c6cbbb
--- /dev/null
+++ b/libc/system_properties/context_node.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef SYSTEM_PROPERTIES_CONTEXT_NODE_H
+#define SYSTEM_PROPERTIES_CONTEXT_NODE_H
+
+#include "private/bionic_lock.h"
+
+#include "prop_area.h"
+
+class ContextNode {
+ public:
+  ContextNode(const char* context) : context_(context), pa_(nullptr), no_access_(false) {
+    lock_.init(false);
+  }
+  ~ContextNode() {
+    Unmap();
+  }
+  bool Open(bool access_rw, bool* fsetxattr_failed);
+  bool CheckAccessAndOpen();
+  void ResetAccess();
+
+  const char* context() const {
+    return context_;
+  }
+  prop_area* pa() {
+    return pa_;
+  }
+
+ private:
+  bool CheckAccess();
+  void Unmap();
+
+  Lock lock_;
+  const char* context_;
+  prop_area* pa_;
+  bool no_access_;
+};
+
+#endif
diff --git a/libc/system_properties/contexts.h b/libc/system_properties/contexts.h
new file mode 100644
index 0000000..5df9d96
--- /dev/null
+++ b/libc/system_properties/contexts.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef SYSTEM_PROPERTIES_CONTEXTS_H
+#define SYSTEM_PROPERTIES_CONTEXTS_H
+
+#include "prop_area.h"
+#include "prop_info.h"
+
+class Contexts {
+ public:
+  virtual ~Contexts() {
+  }
+
+  virtual bool Initialize(bool writable) = 0;
+  virtual prop_area* GetPropAreaForName(const char* name) = 0;
+  virtual prop_area* GetSerialPropArea() = 0;
+  virtual void ForEach(void (*propfn)(const prop_info* pi, void* cookie), void* cookie) = 0;
+  virtual void ResetAccess() = 0;
+  virtual void FreeAndUnmap() = 0;
+};
+
+#endif
diff --git a/libc/system_properties/contexts_pre_split.h b/libc/system_properties/contexts_pre_split.h
new file mode 100644
index 0000000..bbc8529
--- /dev/null
+++ b/libc/system_properties/contexts_pre_split.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef SYSTEM_PROPERTIES_CONTEXTS_PRE_SPLIT_H
+#define SYSTEM_PROPERTIES_CONTEXTS_PRE_SPLIT_H
+
+#include "contexts.h"
+#include "prop_area.h"
+#include "prop_info.h"
+#include "property_filename.h"
+
+class ContextsPreSplit : public Contexts {
+ public:
+  virtual ~ContextsPreSplit() override {
+  }
+
+  // We'll never initialize this legacy option as writable, so don't even check the arg.
+  virtual bool Initialize(bool) override {
+    pre_split_prop_area_ = prop_area::map_prop_area(property_filename);
+    return pre_split_prop_area_ != nullptr;
+  }
+
+  virtual prop_area* GetPropAreaForName(const char*) override {
+    return pre_split_prop_area_;
+  }
+
+  virtual prop_area* GetSerialPropArea() override {
+    return pre_split_prop_area_;
+  }
+
+  virtual void ForEach(void (*propfn)(const prop_info* pi, void* cookie), void* cookie) override {
+    pre_split_prop_area_->foreach (propfn, cookie);
+  }
+
+  // This is a no-op for pre-split properties as there is only one property file and it is
+  // accessible by all domains
+  virtual void ResetAccess() override {
+  }
+
+  virtual void FreeAndUnmap() override {
+    prop_area::unmap_prop_area(&pre_split_prop_area_);
+  }
+
+ private:
+  prop_area* pre_split_prop_area_ = nullptr;
+};
+
+#endif
diff --git a/libc/system_properties/contexts_split.cpp b/libc/system_properties/contexts_split.cpp
new file mode 100644
index 0000000..77f2069
--- /dev/null
+++ b/libc/system_properties/contexts_split.cpp
@@ -0,0 +1,351 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "contexts_split.h"
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include <async_safe/log.h>
+
+#include "context_node.h"
+#include "property_filename.h"
+
+class ContextListNode : public ContextNode {
+ public:
+  ContextListNode(ContextListNode* next, const char* context)
+      : ContextNode(strdup(context)), next(next) {
+  }
+
+  ~ContextListNode() {
+    free(const_cast<char*>(context()));
+  }
+
+  ContextListNode* next;
+};
+
+struct PrefixNode {
+  PrefixNode(struct PrefixNode* next, const char* prefix, ContextListNode* context)
+      : prefix(strdup(prefix)), prefix_len(strlen(prefix)), context(context), next(next) {
+  }
+  ~PrefixNode() {
+    free(prefix);
+  }
+  char* prefix;
+  const size_t prefix_len;
+  ContextListNode* context;
+  PrefixNode* next;
+};
+
+template <typename List, typename... Args>
+static inline void ListAdd(List** list, Args... args) {
+  *list = new List(*list, args...);
+}
+
+static void ListAddAfterLen(PrefixNode** list, const char* prefix, ContextListNode* context) {
+  size_t prefix_len = strlen(prefix);
+
+  auto next_list = list;
+
+  while (*next_list) {
+    if ((*next_list)->prefix_len < prefix_len || (*next_list)->prefix[0] == '*') {
+      ListAdd(next_list, prefix, context);
+      return;
+    }
+    next_list = &(*next_list)->next;
+  }
+  ListAdd(next_list, prefix, context);
+}
+
+template <typename List, typename Func>
+static void ListForEach(List* list, Func func) {
+  while (list) {
+    func(list);
+    list = list->next;
+  }
+}
+
+template <typename List, typename Func>
+static List* ListFind(List* list, Func func) {
+  while (list) {
+    if (func(list)) {
+      return list;
+    }
+    list = list->next;
+  }
+  return nullptr;
+}
+
+template <typename List>
+static void ListFree(List** list) {
+  while (*list) {
+    auto old_list = *list;
+    *list = old_list->next;
+    delete old_list;
+  }
+}
+
+// The below two functions are duplicated from label_support.c in libselinux.
+// TODO: Find a location suitable for these functions such that both libc and
+// libselinux can share a common source file.
+
+// The read_spec_entries and read_spec_entry functions may be used to
+// replace sscanf to read entries from spec files. The file and
+// property services now use these.
+
+// Read an entry from a spec file (e.g. file_contexts)
+static inline int read_spec_entry(char** entry, char** ptr, int* len) {
+  *entry = nullptr;
+  char* tmp_buf = nullptr;
+
+  while (isspace(**ptr) && **ptr != '\0') (*ptr)++;
+
+  tmp_buf = *ptr;
+  *len = 0;
+
+  while (!isspace(**ptr) && **ptr != '\0') {
+    (*ptr)++;
+    (*len)++;
+  }
+
+  if (*len) {
+    *entry = strndup(tmp_buf, *len);
+    if (!*entry) return -1;
+  }
+
+  return 0;
+}
+
+// line_buf - Buffer containing the spec entries .
+// num_args - The number of spec parameter entries to process.
+// ...      - A 'char **spec_entry' for each parameter.
+// returns  - The number of items processed.
+//
+// This function calls read_spec_entry() to do the actual string processing.
+static int read_spec_entries(char* line_buf, int num_args, ...) {
+  char **spec_entry, *buf_p;
+  int len, rc, items, entry_len = 0;
+  va_list ap;
+
+  len = strlen(line_buf);
+  if (line_buf[len - 1] == '\n')
+    line_buf[len - 1] = '\0';
+  else
+    // Handle case if line not \n terminated by bumping
+    // the len for the check below (as the line is NUL
+    // terminated by getline(3))
+    len++;
+
+  buf_p = line_buf;
+  while (isspace(*buf_p)) buf_p++;
+
+  // Skip comment lines and empty lines.
+  if (*buf_p == '#' || *buf_p == '\0') return 0;
+
+  // Process the spec file entries
+  va_start(ap, num_args);
+
+  items = 0;
+  while (items < num_args) {
+    spec_entry = va_arg(ap, char**);
+
+    if (len - 1 == buf_p - line_buf) {
+      va_end(ap);
+      return items;
+    }
+
+    rc = read_spec_entry(spec_entry, &buf_p, &entry_len);
+    if (rc < 0) {
+      va_end(ap);
+      return rc;
+    }
+    if (entry_len) items++;
+  }
+  va_end(ap);
+  return items;
+}
+
+bool ContextsSplit::MapSerialPropertyArea(bool access_rw, bool* fsetxattr_failed) {
+  char filename[PROP_FILENAME_MAX];
+  int len = async_safe_format_buffer(filename, sizeof(filename), "%s/properties_serial",
+                                     property_filename);
+  if (len < 0 || len > PROP_FILENAME_MAX) {
+    serial_prop_area_ = nullptr;
+    return false;
+  }
+
+  if (access_rw) {
+    serial_prop_area_ =
+        prop_area::map_prop_area_rw(filename, "u:object_r:properties_serial:s0", fsetxattr_failed);
+  } else {
+    serial_prop_area_ = prop_area::map_prop_area(filename);
+  }
+  return serial_prop_area_;
+}
+
+bool ContextsSplit::InitializePropertiesFromFile(const char* filename) {
+  FILE* file = fopen(filename, "re");
+  if (!file) {
+    return false;
+  }
+
+  char* buffer = nullptr;
+  size_t line_len;
+  char* prop_prefix = nullptr;
+  char* context = nullptr;
+
+  while (getline(&buffer, &line_len, file) > 0) {
+    int items = read_spec_entries(buffer, 2, &prop_prefix, &context);
+    if (items <= 0) {
+      continue;
+    }
+    if (items == 1) {
+      free(prop_prefix);
+      continue;
+    }
+
+    // init uses ctl.* properties as an IPC mechanism and does not write them
+    // to a property file, therefore we do not need to create property files
+    // to store them.
+    if (!strncmp(prop_prefix, "ctl.", 4)) {
+      free(prop_prefix);
+      free(context);
+      continue;
+    }
+
+    auto old_context = ListFind(
+        contexts_, [context](ContextListNode* l) { return !strcmp(l->context(), context); });
+    if (old_context) {
+      ListAddAfterLen(&prefixes_, prop_prefix, old_context);
+    } else {
+      ListAdd(&contexts_, context);
+      ListAddAfterLen(&prefixes_, prop_prefix, contexts_);
+    }
+    free(prop_prefix);
+    free(context);
+  }
+
+  free(buffer);
+  fclose(file);
+
+  return true;
+}
+
+bool ContextsSplit::InitializeProperties() {
+  // If we do find /property_contexts, then this is being
+  // run as part of the OTA updater on older release that had
+  // /property_contexts - b/34370523
+  if (InitializePropertiesFromFile("/property_contexts")) {
+    return true;
+  }
+
+  // Use property_contexts from /system & /vendor, fall back to those from /
+  if (access("/system/etc/selinux/plat_property_contexts", R_OK) != -1) {
+    if (!InitializePropertiesFromFile("/system/etc/selinux/plat_property_contexts")) {
+      return false;
+    }
+    // Don't check for failure here, so we always have a sane list of properties.
+    // E.g. In case of recovery, the vendor partition will not have mounted and we
+    // still need the system / platform properties to function.
+    InitializePropertiesFromFile("/vendor/etc/selinux/nonplat_property_contexts");
+  } else {
+    if (!InitializePropertiesFromFile("/plat_property_contexts")) {
+      return false;
+    }
+    InitializePropertiesFromFile("/nonplat_property_contexts");
+  }
+
+  return true;
+}
+
+bool ContextsSplit::Initialize(bool writable) {
+  if (!InitializeProperties()) {
+    return false;
+  }
+
+  if (writable) {
+    mkdir(property_filename, S_IRWXU | S_IXGRP | S_IXOTH);
+    bool open_failed = false;
+    bool fsetxattr_failed = false;
+    ListForEach(contexts_, [&fsetxattr_failed, &open_failed](ContextListNode* l) {
+      if (!l->Open(true, &fsetxattr_failed)) {
+        open_failed = true;
+      }
+    });
+    if (open_failed || !MapSerialPropertyArea(true, &fsetxattr_failed)) {
+      FreeAndUnmap();
+      return false;
+    }
+
+    return !fsetxattr_failed;
+  } else {
+    if (!MapSerialPropertyArea(false, nullptr)) {
+      FreeAndUnmap();
+      return false;
+    }
+  }
+  return true;
+}
+
+prop_area* ContextsSplit::GetPropAreaForName(const char* name) {
+  auto entry = ListFind(prefixes_, [name](PrefixNode* l) {
+    return l->prefix[0] == '*' || !strncmp(l->prefix, name, l->prefix_len);
+  });
+  if (!entry) {
+    return nullptr;
+  }
+
+  auto cnode = entry->context;
+  if (!cnode->pa()) {
+    // We explicitly do not check no_access_ in this case because unlike the
+    // case of foreach(), we want to generate an selinux audit for each
+    // non-permitted property access in this function.
+    cnode->Open(false, nullptr);
+  }
+  return cnode->pa();
+}
+
+void ContextsSplit::ForEach(void (*propfn)(const prop_info* pi, void* cookie), void* cookie) {
+  ListForEach(contexts_, [propfn, cookie](ContextListNode* l) {
+    if (l->CheckAccessAndOpen()) {
+      l->pa()->foreach (propfn, cookie);
+    }
+  });
+}
+
+void ContextsSplit::ResetAccess() {
+  ListForEach(contexts_, [](ContextListNode* l) { l->ResetAccess(); });
+}
+
+void ContextsSplit::FreeAndUnmap() {
+  ListFree(&prefixes_);
+  ListFree(&contexts_);
+  prop_area::unmap_prop_area(&serial_prop_area_);
+}
diff --git a/libc/system_properties/contexts_split.h b/libc/system_properties/contexts_split.h
new file mode 100644
index 0000000..f98eb44
--- /dev/null
+++ b/libc/system_properties/contexts_split.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef SYSTEM_PROPERTIES_CONTEXTS_SPLIT_H
+#define SYSTEM_PROPERTIES_CONTEXTS_SPLIT_H
+
+#include "contexts.h"
+
+struct PrefixNode;
+class ContextListNode;
+
+class ContextsSplit : public Contexts {
+ public:
+  virtual ~ContextsSplit() override {
+  }
+
+  virtual bool Initialize(bool writable) override;
+  virtual prop_area* GetPropAreaForName(const char* name) override;
+  virtual prop_area* GetSerialPropArea() override {
+    return serial_prop_area_;
+  }
+  virtual void ForEach(void (*propfn)(const prop_info* pi, void* cookie), void* cookie) override;
+  virtual void ResetAccess() override;
+  virtual void FreeAndUnmap() override;
+
+ private:
+  bool MapSerialPropertyArea(bool access_rw, bool* fsetxattr_failed);
+  bool InitializePropertiesFromFile(const char* filename);
+  bool InitializeProperties();
+
+  PrefixNode* prefixes_ = nullptr;
+  ContextListNode* contexts_ = nullptr;
+  prop_area* serial_prop_area_ = nullptr;
+};
+
+#endif
diff --git a/libc/system_properties/prop_area.cpp b/libc/system_properties/prop_area.cpp
new file mode 100644
index 0000000..e11f292
--- /dev/null
+++ b/libc/system_properties/prop_area.cpp
@@ -0,0 +1,372 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/cdefs.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/xattr.h>
+#include <unistd.h>
+
+#include <new>
+
+#include <async_safe/log.h>
+
+#include "prop_area.h"
+
+constexpr size_t PA_SIZE = 128 * 1024;
+constexpr uint32_t PROP_AREA_MAGIC = 0x504f5250;
+constexpr uint32_t PROP_AREA_VERSION = 0xfc6ed0ab;
+
+size_t prop_area::pa_size_ = 0;
+size_t prop_area::pa_data_size_ = 0;
+
+prop_area* prop_area::map_prop_area_rw(const char* filename, const char* context,
+                                       bool* fsetxattr_failed) {
+  /* dev is a tmpfs that we can use to carve a shared workspace
+   * out of, so let's do that...
+   */
+  const int fd = open(filename, O_RDWR | O_CREAT | O_NOFOLLOW | O_CLOEXEC | O_EXCL, 0444);
+
+  if (fd < 0) {
+    if (errno == EACCES) {
+      /* for consistency with the case where the process has already
+       * mapped the page in and segfaults when trying to write to it
+       */
+      abort();
+    }
+    return nullptr;
+  }
+
+  if (context) {
+    if (fsetxattr(fd, XATTR_NAME_SELINUX, context, strlen(context) + 1, 0) != 0) {
+      async_safe_format_log(ANDROID_LOG_ERROR, "libc",
+                            "fsetxattr failed to set context (%s) for \"%s\"", context, filename);
+      /*
+       * fsetxattr() will fail during system properties tests due to selinux policy.
+       * We do not want to create a custom policy for the tester, so we will continue in
+       * this function but set a flag that an error has occurred.
+       * Init, which is the only daemon that should ever call this function will abort
+       * when this error occurs.
+       * Otherwise, the tester will ignore it and continue, albeit without any selinux
+       * property separation.
+       */
+      if (fsetxattr_failed) {
+        *fsetxattr_failed = true;
+      }
+    }
+  }
+
+  if (ftruncate(fd, PA_SIZE) < 0) {
+    close(fd);
+    return nullptr;
+  }
+
+  pa_size_ = PA_SIZE;
+  pa_data_size_ = pa_size_ - sizeof(prop_area);
+
+  void* const memory_area = mmap(nullptr, pa_size_, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+  if (memory_area == MAP_FAILED) {
+    close(fd);
+    return nullptr;
+  }
+
+  prop_area* pa = new (memory_area) prop_area(PROP_AREA_MAGIC, PROP_AREA_VERSION);
+
+  close(fd);
+  return pa;
+}
+
+prop_area* prop_area::map_fd_ro(const int fd) {
+  struct stat fd_stat;
+  if (fstat(fd, &fd_stat) < 0) {
+    return nullptr;
+  }
+
+  if ((fd_stat.st_uid != 0) || (fd_stat.st_gid != 0) ||
+      ((fd_stat.st_mode & (S_IWGRP | S_IWOTH)) != 0) ||
+      (fd_stat.st_size < static_cast<off_t>(sizeof(prop_area)))) {
+    return nullptr;
+  }
+
+  pa_size_ = fd_stat.st_size;
+  pa_data_size_ = pa_size_ - sizeof(prop_area);
+
+  void* const map_result = mmap(nullptr, pa_size_, PROT_READ, MAP_SHARED, fd, 0);
+  if (map_result == MAP_FAILED) {
+    return nullptr;
+  }
+
+  prop_area* pa = reinterpret_cast<prop_area*>(map_result);
+  if ((pa->magic() != PROP_AREA_MAGIC) || (pa->version() != PROP_AREA_VERSION)) {
+    munmap(pa, pa_size_);
+    return nullptr;
+  }
+
+  return pa;
+}
+
+prop_area* prop_area::map_prop_area(const char* filename) {
+  int fd = open(filename, O_CLOEXEC | O_NOFOLLOW | O_RDONLY);
+  if (fd == -1) return nullptr;
+
+  prop_area* map_result = map_fd_ro(fd);
+  close(fd);
+
+  return map_result;
+}
+
+void* prop_area::allocate_obj(const size_t size, uint_least32_t* const off) {
+  const size_t aligned = __BIONIC_ALIGN(size, sizeof(uint_least32_t));
+  if (bytes_used_ + aligned > pa_data_size_) {
+    return nullptr;
+  }
+
+  *off = bytes_used_;
+  bytes_used_ += aligned;
+  return data_ + *off;
+}
+
+prop_bt* prop_area::new_prop_bt(const char* name, uint32_t namelen, uint_least32_t* const off) {
+  uint_least32_t new_offset;
+  void* const p = allocate_obj(sizeof(prop_bt) + namelen + 1, &new_offset);
+  if (p != nullptr) {
+    prop_bt* bt = new (p) prop_bt(name, namelen);
+    *off = new_offset;
+    return bt;
+  }
+
+  return nullptr;
+}
+
+prop_info* prop_area::new_prop_info(const char* name, uint32_t namelen, const char* value,
+                                    uint32_t valuelen, uint_least32_t* const off) {
+  uint_least32_t new_offset;
+  void* const p = allocate_obj(sizeof(prop_info) + namelen + 1, &new_offset);
+  if (p == nullptr) return nullptr;
+
+  prop_info* info;
+  if (valuelen >= PROP_VALUE_MAX) {
+    uint32_t long_value_offset = 0;
+    char* long_location = reinterpret_cast<char*>(allocate_obj(valuelen + 1, &long_value_offset));
+    if (!long_location) return nullptr;
+
+    memcpy(long_location, value, valuelen);
+    long_location[valuelen] = '\0';
+
+    // Both new_offset and long_value_offset are offsets based off of data_, however prop_info
+    // does not know what data_ is, so we change this offset to be an offset from the prop_info
+    // pointer that contains it.
+    long_value_offset -= new_offset;
+
+    info = new (p) prop_info(name, namelen, long_value_offset);
+  } else {
+    info = new (p) prop_info(name, namelen, value, valuelen);
+  }
+  *off = new_offset;
+  return info;
+}
+
+void* prop_area::to_prop_obj(uint_least32_t off) {
+  if (off > pa_data_size_) return nullptr;
+
+  return (data_ + off);
+}
+
+inline prop_bt* prop_area::to_prop_bt(atomic_uint_least32_t* off_p) {
+  uint_least32_t off = atomic_load_explicit(off_p, memory_order_consume);
+  return reinterpret_cast<prop_bt*>(to_prop_obj(off));
+}
+
+inline prop_info* prop_area::to_prop_info(atomic_uint_least32_t* off_p) {
+  uint_least32_t off = atomic_load_explicit(off_p, memory_order_consume);
+  return reinterpret_cast<prop_info*>(to_prop_obj(off));
+}
+
+inline prop_bt* prop_area::root_node() {
+  return reinterpret_cast<prop_bt*>(to_prop_obj(0));
+}
+
+static int cmp_prop_name(const char* one, uint32_t one_len, const char* two, uint32_t two_len) {
+  if (one_len < two_len)
+    return -1;
+  else if (one_len > two_len)
+    return 1;
+  else
+    return strncmp(one, two, one_len);
+}
+
+prop_bt* prop_area::find_prop_bt(prop_bt* const bt, const char* name, uint32_t namelen,
+                                 bool alloc_if_needed) {
+  prop_bt* current = bt;
+  while (true) {
+    if (!current) {
+      return nullptr;
+    }
+
+    const int ret = cmp_prop_name(name, namelen, current->name, current->namelen);
+    if (ret == 0) {
+      return current;
+    }
+
+    if (ret < 0) {
+      uint_least32_t left_offset = atomic_load_explicit(&current->left, memory_order_relaxed);
+      if (left_offset != 0) {
+        current = to_prop_bt(&current->left);
+      } else {
+        if (!alloc_if_needed) {
+          return nullptr;
+        }
+
+        uint_least32_t new_offset;
+        prop_bt* new_bt = new_prop_bt(name, namelen, &new_offset);
+        if (new_bt) {
+          atomic_store_explicit(&current->left, new_offset, memory_order_release);
+        }
+        return new_bt;
+      }
+    } else {
+      uint_least32_t right_offset = atomic_load_explicit(&current->right, memory_order_relaxed);
+      if (right_offset != 0) {
+        current = to_prop_bt(&current->right);
+      } else {
+        if (!alloc_if_needed) {
+          return nullptr;
+        }
+
+        uint_least32_t new_offset;
+        prop_bt* new_bt = new_prop_bt(name, namelen, &new_offset);
+        if (new_bt) {
+          atomic_store_explicit(&current->right, new_offset, memory_order_release);
+        }
+        return new_bt;
+      }
+    }
+  }
+}
+
+const prop_info* prop_area::find_property(prop_bt* const trie, const char* name, uint32_t namelen,
+                                          const char* value, uint32_t valuelen,
+                                          bool alloc_if_needed) {
+  if (!trie) return nullptr;
+
+  const char* remaining_name = name;
+  prop_bt* current = trie;
+  while (true) {
+    const char* sep = strchr(remaining_name, '.');
+    const bool want_subtree = (sep != nullptr);
+    const uint32_t substr_size = (want_subtree) ? sep - remaining_name : strlen(remaining_name);
+
+    if (!substr_size) {
+      return nullptr;
+    }
+
+    prop_bt* root = nullptr;
+    uint_least32_t children_offset = atomic_load_explicit(&current->children, memory_order_relaxed);
+    if (children_offset != 0) {
+      root = to_prop_bt(&current->children);
+    } else if (alloc_if_needed) {
+      uint_least32_t new_offset;
+      root = new_prop_bt(remaining_name, substr_size, &new_offset);
+      if (root) {
+        atomic_store_explicit(&current->children, new_offset, memory_order_release);
+      }
+    }
+
+    if (!root) {
+      return nullptr;
+    }
+
+    current = find_prop_bt(root, remaining_name, substr_size, alloc_if_needed);
+    if (!current) {
+      return nullptr;
+    }
+
+    if (!want_subtree) break;
+
+    remaining_name = sep + 1;
+  }
+
+  uint_least32_t prop_offset = atomic_load_explicit(&current->prop, memory_order_relaxed);
+  if (prop_offset != 0) {
+    return to_prop_info(&current->prop);
+  } else if (alloc_if_needed) {
+    uint_least32_t new_offset;
+    prop_info* new_info = new_prop_info(name, namelen, value, valuelen, &new_offset);
+    if (new_info) {
+      atomic_store_explicit(&current->prop, new_offset, memory_order_release);
+    }
+
+    return new_info;
+  } else {
+    return nullptr;
+  }
+}
+
+bool prop_area::foreach_property(prop_bt* const trie,
+                                 void (*propfn)(const prop_info* pi, void* cookie), void* cookie) {
+  if (!trie) return false;
+
+  uint_least32_t left_offset = atomic_load_explicit(&trie->left, memory_order_relaxed);
+  if (left_offset != 0) {
+    const int err = foreach_property(to_prop_bt(&trie->left), propfn, cookie);
+    if (err < 0) return false;
+  }
+  uint_least32_t prop_offset = atomic_load_explicit(&trie->prop, memory_order_relaxed);
+  if (prop_offset != 0) {
+    prop_info* info = to_prop_info(&trie->prop);
+    if (!info) return false;
+    propfn(info, cookie);
+  }
+  uint_least32_t children_offset = atomic_load_explicit(&trie->children, memory_order_relaxed);
+  if (children_offset != 0) {
+    const int err = foreach_property(to_prop_bt(&trie->children), propfn, cookie);
+    if (err < 0) return false;
+  }
+  uint_least32_t right_offset = atomic_load_explicit(&trie->right, memory_order_relaxed);
+  if (right_offset != 0) {
+    const int err = foreach_property(to_prop_bt(&trie->right), propfn, cookie);
+    if (err < 0) return false;
+  }
+
+  return true;
+}
+
+const prop_info* prop_area::find(const char* name) {
+  return find_property(root_node(), name, strlen(name), nullptr, 0, false);
+}
+
+bool prop_area::add(const char* name, unsigned int namelen, const char* value,
+                    unsigned int valuelen) {
+  return find_property(root_node(), name, namelen, value, valuelen, true);
+}
+
+bool prop_area::foreach (void (*propfn)(const prop_info* pi, void* cookie), void* cookie) {
+  return foreach_property(root_node(), propfn, cookie);
+}
diff --git a/libc/system_properties/prop_area.h b/libc/system_properties/prop_area.h
new file mode 100644
index 0000000..10c1adb
--- /dev/null
+++ b/libc/system_properties/prop_area.h
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdatomic.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/mman.h>
+
+#include "private/bionic_macros.h"
+
+#include "prop_info.h"
+
+#ifndef SYSTEM_PROPERTIES_PROP_AREA_H
+#define SYSTEM_PROPERTIES_PROP_AREA_H
+
+// Properties are stored in a hybrid trie/binary tree structure.
+// Each property's name is delimited at '.' characters, and the tokens are put
+// into a trie structure.  Siblings at each level of the trie are stored in a
+// binary tree.  For instance, "ro.secure"="1" could be stored as follows:
+//
+// +-----+   children    +----+   children    +--------+
+// |     |-------------->| ro |-------------->| secure |
+// +-----+               +----+               +--------+
+//                       /    \                /   |
+//                 left /      \ right   left /    |  prop   +===========+
+//                     v        v            v     +-------->| ro.secure |
+//                  +-----+   +-----+     +-----+            +-----------+
+//                  | net |   | sys |     | com |            |     1     |
+//                  +-----+   +-----+     +-----+            +===========+
+
+// Represents a node in the trie.
+struct prop_bt {
+  uint32_t namelen;
+
+  // The property trie is updated only by the init process (single threaded) which provides
+  // property service. And it can be read by multiple threads at the same time.
+  // As the property trie is not protected by locks, we use atomic_uint_least32_t types for the
+  // left, right, children "pointers" in the trie node. To make sure readers who see the
+  // change of "pointers" can also notice the change of prop_bt structure contents pointed by
+  // the "pointers", we always use release-consume ordering pair when accessing these "pointers".
+
+  // prop "points" to prop_info structure if there is a propery associated with the trie node.
+  // Its situation is similar to the left, right, children "pointers". So we use
+  // atomic_uint_least32_t and release-consume ordering to protect it as well.
+
+  // We should also avoid rereading these fields redundantly, since not
+  // all processor implementations ensure that multiple loads from the
+  // same field are carried out in the right order.
+  atomic_uint_least32_t prop;
+
+  atomic_uint_least32_t left;
+  atomic_uint_least32_t right;
+
+  atomic_uint_least32_t children;
+
+  char name[0];
+
+  prop_bt(const char* name, const uint32_t name_length) {
+    this->namelen = name_length;
+    memcpy(this->name, name, name_length);
+    this->name[name_length] = '\0';
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(prop_bt);
+};
+
+class prop_area {
+ public:
+  static prop_area* map_prop_area_rw(const char* filename, const char* context,
+                                     bool* fsetxattr_failed);
+  static prop_area* map_prop_area(const char* filename);
+  static void unmap_prop_area(prop_area** pa) {
+    if (*pa) {
+      munmap(*pa, pa_size_);
+      *pa = nullptr;
+    }
+  }
+
+  prop_area(const uint32_t magic, const uint32_t version) : magic_(magic), version_(version) {
+    atomic_init(&serial_, 0);
+    memset(reserved_, 0, sizeof(reserved_));
+    // Allocate enough space for the root node.
+    bytes_used_ = sizeof(prop_bt);
+  }
+
+  const prop_info* find(const char* name);
+  bool add(const char* name, unsigned int namelen, const char* value, unsigned int valuelen);
+
+  bool foreach (void (*propfn)(const prop_info* pi, void* cookie), void* cookie);
+
+  atomic_uint_least32_t* serial() {
+    return &serial_;
+  }
+  uint32_t magic() const {
+    return magic_;
+  }
+  uint32_t version() const {
+    return version_;
+  }
+
+ private:
+  static prop_area* map_fd_ro(const int fd);
+
+  void* allocate_obj(const size_t size, uint_least32_t* const off);
+  prop_bt* new_prop_bt(const char* name, uint32_t namelen, uint_least32_t* const off);
+  prop_info* new_prop_info(const char* name, uint32_t namelen, const char* value, uint32_t valuelen,
+                           uint_least32_t* const off);
+  void* to_prop_obj(uint_least32_t off);
+  prop_bt* to_prop_bt(atomic_uint_least32_t* off_p);
+  prop_info* to_prop_info(atomic_uint_least32_t* off_p);
+
+  prop_bt* root_node();
+
+  prop_bt* find_prop_bt(prop_bt* const bt, const char* name, uint32_t namelen, bool alloc_if_needed);
+
+  const prop_info* find_property(prop_bt* const trie, const char* name, uint32_t namelen,
+                                 const char* value, uint32_t valuelen, bool alloc_if_needed);
+
+  bool foreach_property(prop_bt* const trie, void (*propfn)(const prop_info* pi, void* cookie),
+                        void* cookie);
+
+  // The original design doesn't include pa_size or pa_data_size in the prop_area struct itself.
+  // Since we'll need to be backwards compatible with that design, we don't gain much by adding it
+  // now, especially since we don't have any plans to make different property areas different sizes,
+  // and thus we share these two variables among all instances.
+  static size_t pa_size_;
+  static size_t pa_data_size_;
+
+  uint32_t bytes_used_;
+  atomic_uint_least32_t serial_;
+  uint32_t magic_;
+  uint32_t version_;
+  uint32_t reserved_[28];
+  char data_[0];
+
+  DISALLOW_COPY_AND_ASSIGN(prop_area);
+};
+
+#endif
diff --git a/libc/system_properties/prop_info.cpp b/libc/system_properties/prop_info.cpp
new file mode 100644
index 0000000..5123f92
--- /dev/null
+++ b/libc/system_properties/prop_info.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "prop_info.h"
+
+#include <string.h>
+
+constexpr static const char kLongLegacyError[] =
+    "Must use __system_property_read_callback() to read";
+static_assert(sizeof(kLongLegacyError) < prop_info::kLongLegacyErrorBufferSize,
+              "Error message for long properties read by legacy libc must fit within 56 chars");
+
+prop_info::prop_info(const char* name, uint32_t namelen, const char* value, uint32_t valuelen) {
+  memcpy(this->name, name, namelen);
+  this->name[namelen] = '\0';
+  atomic_init(&this->serial, valuelen << 24);
+  memcpy(this->value, value, valuelen);
+  this->value[valuelen] = '\0';
+}
+
+prop_info::prop_info(const char* name, uint32_t namelen, uint32_t long_offset) {
+  memcpy(this->name, name, namelen);
+  this->name[namelen] = '\0';
+
+  auto error_value_len = sizeof(kLongLegacyError) - 1;
+  atomic_init(&this->serial, error_value_len << 24 | kLongFlag);
+  memcpy(this->long_property.error_message, kLongLegacyError, sizeof(kLongLegacyError));
+
+  this->long_property.offset = long_offset;
+}
diff --git a/libc/system_properties/prop_info.h b/libc/system_properties/prop_info.h
new file mode 100644
index 0000000..99bcaaf
--- /dev/null
+++ b/libc/system_properties/prop_info.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdatomic.h>
+#include <stdint.h>
+#include <sys/system_properties.h>
+
+#include "private/bionic_macros.h"
+
+#ifndef SYSTEM_PROPERTIES_PROP_INFO_H
+#define SYSTEM_PROPERTIES_PROP_INFO_H
+
+// The C11 standard doesn't allow atomic loads from const fields,
+// though C++11 does.  Fudge it until standards get straightened out.
+static inline uint_least32_t load_const_atomic(const atomic_uint_least32_t* s, memory_order mo) {
+  atomic_uint_least32_t* non_const_s = const_cast<atomic_uint_least32_t*>(s);
+  return atomic_load_explicit(non_const_s, mo);
+}
+
+struct prop_info {
+  // Read only properties will not set anything but the bottom most bit of serial and the top byte.
+  // We borrow the 2nd from the top byte for extra flags, and use the bottom most bit of that for
+  // our first user, kLongFlag.
+  constexpr static uint32_t kLongFlag = 1 << 16;
+
+  // The error message fits in part of a union with the previous 92 char property value so there
+  // must be room left over after the error message for the offset to the new longer property value
+  // and future expansion fields if needed. Note that this value cannot ever increase.  The offset
+  // to the new longer property value appears immediately after it, so an increase of this size will
+  // break compatibility.
+  constexpr static size_t kLongLegacyErrorBufferSize = 56;
+
+ public:
+  atomic_uint_least32_t serial;
+  // we need to keep this buffer around because the property
+  // value can be modified whereas name is constant.
+  union {
+    char value[PROP_VALUE_MAX];
+    struct {
+      char error_message[kLongLegacyErrorBufferSize];
+      uint32_t offset;
+    } long_property;
+  };
+  char name[0];
+
+  bool is_long() const {
+    return (load_const_atomic(&serial, memory_order_relaxed) & kLongFlag) != 0;
+  }
+
+  const char* long_value() const {
+    // We can't store pointers here since this is shared memory that will have different absolute
+    // pointers in different processes.  We don't have data_ from prop_area, but since we know
+    // `this` is data_ + some offset and long_value is data_ + some other offset, we calculate the
+    // offset from `this` to long_value and store it as long_property.offset.
+    return reinterpret_cast<const char*>(this) + long_property.offset;
+  }
+
+  prop_info(const char* name, uint32_t namelen, const char* value, uint32_t valuelen);
+  prop_info(const char* name, uint32_t namelen, uint32_t long_offset);
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(prop_info);
+};
+
+static_assert(sizeof(prop_info) == 96, "sizeof struct prop_info must be 96 bytes");
+
+#endif
diff --git a/libc/system_properties/property_filename.h b/libc/system_properties/property_filename.h
new file mode 100644
index 0000000..0f7bcf7
--- /dev/null
+++ b/libc/system_properties/property_filename.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef SYSTEM_PROPERTIES_PROPERTY_FILENAME_H
+#define SYSTEM_PROPERTIES_PROPERTY_FILENAME_H
+
+// These are globals set by __system_property_set_filename().
+// There isn't huge benefit in refactoring them, so they're alone in this header.
+constexpr int PROP_FILENAME_MAX = 1024;
+extern char property_filename[PROP_FILENAME_MAX];
+
+#endif
diff --git a/libc/system_properties/system_properties.cpp b/libc/system_properties/system_properties.cpp
new file mode 100644
index 0000000..3f6601d
--- /dev/null
+++ b/libc/system_properties/system_properties.cpp
@@ -0,0 +1,675 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <poll.h>
+#include <stdatomic.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
+#include <sys/_system_properties.h>
+#include <sys/system_properties.h>
+
+#include <async_safe/log.h>
+
+#include "private/ErrnoRestorer.h"
+#include "private/bionic_defs.h"
+#include "private/bionic_futex.h"
+#include "private/bionic_macros.h"
+#include "private/bionic_sdk_version.h"
+
+#include "context_node.h"
+#include "contexts.h"
+#include "contexts_pre_split.h"
+#include "contexts_split.h"
+#include "prop_area.h"
+#include "prop_info.h"
+#include "property_filename.h"
+
+// We don't want to use new or malloc in properties (b/31659220), and since these classes are
+// small enough and don't have non-trivial constructors, it's easier to just statically declare
+// them than anything else.
+static ContextsSplit contexts_split;
+static ContextsPreSplit contexts_pre_split;
+static Contexts* contexts = nullptr;
+
+#define SERIAL_DIRTY(serial) ((serial)&1)
+#define SERIAL_VALUE_LEN(serial) ((serial) >> 24)
+
+static const char property_service_socket[] = "/dev/socket/" PROP_SERVICE_NAME;
+static const char* kServiceVersionPropertyName = "ro.property_service.version";
+
+// This is public because it was exposed in the NDK. As of 2017-01, ~60 apps reference this symbol.
+// It is set to nullptr and never modified.
+__BIONIC_WEAK_VARIABLE_FOR_NATIVE_BRIDGE
+prop_area* __system_property_area__ = nullptr;
+
+char property_filename[PROP_FILENAME_MAX] = PROP_FILENAME;
+
+class PropertyServiceConnection {
+ public:
+  PropertyServiceConnection() : last_error_(0) {
+    socket_ = ::socket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
+    if (socket_ == -1) {
+      last_error_ = errno;
+      return;
+    }
+
+    const size_t namelen = strlen(property_service_socket);
+    sockaddr_un addr;
+    memset(&addr, 0, sizeof(addr));
+    strlcpy(addr.sun_path, property_service_socket, sizeof(addr.sun_path));
+    addr.sun_family = AF_LOCAL;
+    socklen_t alen = namelen + offsetof(sockaddr_un, sun_path) + 1;
+
+    if (TEMP_FAILURE_RETRY(connect(socket_, reinterpret_cast<sockaddr*>(&addr), alen)) == -1) {
+      last_error_ = errno;
+      close(socket_);
+      socket_ = -1;
+    }
+  }
+
+  bool IsValid() {
+    return socket_ != -1;
+  }
+
+  int GetLastError() {
+    return last_error_;
+  }
+
+  bool RecvInt32(int32_t* value) {
+    int result = TEMP_FAILURE_RETRY(recv(socket_, value, sizeof(*value), MSG_WAITALL));
+    return CheckSendRecvResult(result, sizeof(*value));
+  }
+
+  int socket() {
+    return socket_;
+  }
+
+  ~PropertyServiceConnection() {
+    if (socket_ != -1) {
+      close(socket_);
+    }
+  }
+
+ private:
+  bool CheckSendRecvResult(int result, int expected_len) {
+    if (result == -1) {
+      last_error_ = errno;
+    } else if (result != expected_len) {
+      last_error_ = -1;
+    } else {
+      last_error_ = 0;
+    }
+
+    return last_error_ == 0;
+  }
+
+  int socket_;
+  int last_error_;
+
+  friend class SocketWriter;
+};
+
+class SocketWriter {
+ public:
+  explicit SocketWriter(PropertyServiceConnection* connection)
+      : connection_(connection), iov_index_(0), uint_buf_index_(0) {
+  }
+
+  SocketWriter& WriteUint32(uint32_t value) {
+    CHECK(uint_buf_index_ < kUintBufSize);
+    CHECK(iov_index_ < kIovSize);
+    uint32_t* ptr = uint_buf_ + uint_buf_index_;
+    uint_buf_[uint_buf_index_++] = value;
+    iov_[iov_index_].iov_base = ptr;
+    iov_[iov_index_].iov_len = sizeof(*ptr);
+    ++iov_index_;
+    return *this;
+  }
+
+  SocketWriter& WriteString(const char* value) {
+    uint32_t valuelen = strlen(value);
+    WriteUint32(valuelen);
+    if (valuelen == 0) {
+      return *this;
+    }
+
+    CHECK(iov_index_ < kIovSize);
+    iov_[iov_index_].iov_base = const_cast<char*>(value);
+    iov_[iov_index_].iov_len = valuelen;
+    ++iov_index_;
+
+    return *this;
+  }
+
+  bool Send() {
+    if (!connection_->IsValid()) {
+      return false;
+    }
+
+    if (writev(connection_->socket(), iov_, iov_index_) == -1) {
+      connection_->last_error_ = errno;
+      return false;
+    }
+
+    iov_index_ = uint_buf_index_ = 0;
+    return true;
+  }
+
+ private:
+  static constexpr size_t kUintBufSize = 8;
+  static constexpr size_t kIovSize = 8;
+
+  PropertyServiceConnection* connection_;
+  iovec iov_[kIovSize];
+  size_t iov_index_;
+  uint32_t uint_buf_[kUintBufSize];
+  size_t uint_buf_index_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(SocketWriter);
+};
+
+struct prop_msg {
+  unsigned cmd;
+  char name[PROP_NAME_MAX];
+  char value[PROP_VALUE_MAX];
+};
+
+static int send_prop_msg(const prop_msg* msg) {
+  PropertyServiceConnection connection;
+  if (!connection.IsValid()) {
+    return connection.GetLastError();
+  }
+
+  int result = -1;
+  int s = connection.socket();
+
+  const int num_bytes = TEMP_FAILURE_RETRY(send(s, msg, sizeof(prop_msg), 0));
+  if (num_bytes == sizeof(prop_msg)) {
+    // We successfully wrote to the property server but now we
+    // wait for the property server to finish its work.  It
+    // acknowledges its completion by closing the socket so we
+    // poll here (on nothing), waiting for the socket to close.
+    // If you 'adb shell setprop foo bar' you'll see the POLLHUP
+    // once the socket closes.  Out of paranoia we cap our poll
+    // at 250 ms.
+    pollfd pollfds[1];
+    pollfds[0].fd = s;
+    pollfds[0].events = 0;
+    const int poll_result = TEMP_FAILURE_RETRY(poll(pollfds, 1, 250 /* ms */));
+    if (poll_result == 1 && (pollfds[0].revents & POLLHUP) != 0) {
+      result = 0;
+    } else {
+      // Ignore the timeout and treat it like a success anyway.
+      // The init process is single-threaded and its property
+      // service is sometimes slow to respond (perhaps it's off
+      // starting a child process or something) and thus this
+      // times out and the caller thinks it failed, even though
+      // it's still getting around to it.  So we fake it here,
+      // mostly for ctl.* properties, but we do try and wait 250
+      // ms so callers who do read-after-write can reliably see
+      // what they've written.  Most of the time.
+      // TODO: fix the system properties design.
+      async_safe_format_log(ANDROID_LOG_WARN, "libc",
+                            "Property service has timed out while trying to set \"%s\" to \"%s\"",
+                            msg->name, msg->value);
+      result = 0;
+    }
+  }
+
+  return result;
+}
+
+static bool is_dir(const char* pathname) {
+  struct stat info;
+  if (stat(pathname, &info) == -1) {
+    return false;
+  }
+  return S_ISDIR(info.st_mode);
+}
+
+__BIONIC_WEAK_FOR_NATIVE_BRIDGE
+int __system_properties_init() {
+  // This is called from __libc_init_common, and should leave errno at 0 (http://b/37248982).
+  ErrnoRestorer errno_restorer;
+
+  if (contexts != nullptr) {
+    contexts->ResetAccess();
+    return 0;
+  }
+  contexts = nullptr;
+  if (is_dir(property_filename)) {
+    if (!contexts_split.Initialize(false)) {
+      return -1;
+    }
+    contexts = &contexts_split;
+  } else {
+    if (!contexts_pre_split.Initialize(false)) {
+      return -1;
+    }
+    contexts = &contexts_pre_split;
+  }
+  return 0;
+}
+
+__BIONIC_WEAK_FOR_NATIVE_BRIDGE
+int __system_property_set_filename(const char* filename) {
+  size_t len = strlen(filename);
+  if (len >= sizeof(property_filename)) return -1;
+
+  strcpy(property_filename, filename);
+  return 0;
+}
+
+__BIONIC_WEAK_FOR_NATIVE_BRIDGE
+int __system_property_area_init() {
+  if (contexts != nullptr) {
+    contexts->FreeAndUnmap();
+  }
+  // We set this unconditionally as we want tests to continue on regardless of if this failed
+  // and property_service will abort on an error condition, so no harm done.
+  contexts = &contexts_split;
+  if (!contexts_split.Initialize(true)) {
+    return -1;
+  }
+  return 0;
+}
+
+__BIONIC_WEAK_FOR_NATIVE_BRIDGE
+uint32_t __system_property_area_serial() {
+  if (contexts == nullptr) {
+    return -1;
+  }
+
+  prop_area* pa = contexts->GetSerialPropArea();
+  if (!pa) {
+    return -1;
+  }
+
+  // Make sure this read fulfilled before __system_property_serial
+  return atomic_load_explicit(pa->serial(), memory_order_acquire);
+}
+
+__BIONIC_WEAK_FOR_NATIVE_BRIDGE
+const prop_info* __system_property_find(const char* name) {
+  if (contexts == nullptr) {
+    return nullptr;
+  }
+
+  prop_area* pa = contexts->GetPropAreaForName(name);
+  if (!pa) {
+    async_safe_format_log(ANDROID_LOG_ERROR, "libc", "Access denied finding property \"%s\"", name);
+    return nullptr;
+  }
+
+  return pa->find(name);
+}
+
+static bool is_read_only(const char* name) {
+  return strncmp(name, "ro.", 3) == 0;
+}
+
+__BIONIC_WEAK_FOR_NATIVE_BRIDGE
+int __system_property_read(const prop_info* pi, char* name, char* value) {
+  while (true) {
+    uint32_t serial = __system_property_serial(pi);  // acquire semantics
+    size_t len = SERIAL_VALUE_LEN(serial);
+    memcpy(value, pi->value, len + 1);
+    // TODO: Fix the synchronization scheme here.
+    // There is no fully supported way to implement this kind
+    // of synchronization in C++11, since the memcpy races with
+    // updates to pi, and the data being accessed is not atomic.
+    // The following fence is unintuitive, but would be the
+    // correct one if memcpy used memory_order_relaxed atomic accesses.
+    // In practice it seems unlikely that the generated code would
+    // would be any different, so this should be OK.
+    atomic_thread_fence(memory_order_acquire);
+    if (serial == load_const_atomic(&(pi->serial), memory_order_relaxed)) {
+      if (name != nullptr) {
+        size_t namelen = strlcpy(name, pi->name, PROP_NAME_MAX);
+        if (namelen >= PROP_NAME_MAX) {
+          async_safe_format_log(ANDROID_LOG_ERROR, "libc",
+                                "The property name length for \"%s\" is >= %d;"
+                                " please use __system_property_read_callback"
+                                " to read this property. (the name is truncated to \"%s\")",
+                                pi->name, PROP_NAME_MAX - 1, name);
+        }
+      }
+      if (is_read_only(pi->name) && pi->is_long()) {
+        async_safe_format_log(
+            ANDROID_LOG_ERROR, "libc",
+            "The property \"%s\" has a value with length %zu that is too large for"
+            " __system_property_get()/__system_property_read(); use"
+            " __system_property_read_callback() instead.",
+            pi->name, strlen(pi->long_value()));
+      }
+      return len;
+    }
+  }
+}
+
+__BIONIC_WEAK_FOR_NATIVE_BRIDGE
+void __system_property_read_callback(const prop_info* pi,
+                                     void (*callback)(void* cookie, const char* name,
+                                                      const char* value, uint32_t serial),
+                                     void* cookie) {
+  // Read only properties don't need to copy the value to a temporary buffer, since it can never
+  // change.
+  if (is_read_only(pi->name)) {
+    uint32_t serial = __system_property_serial(pi);
+    if (pi->is_long()) {
+      callback(cookie, pi->name, pi->long_value(), serial);
+    } else {
+      callback(cookie, pi->name, pi->value, serial);
+    }
+    return;
+  }
+
+  while (true) {
+    uint32_t serial = __system_property_serial(pi);  // acquire semantics
+    size_t len = SERIAL_VALUE_LEN(serial);
+    char value_buf[len + 1];
+
+    memcpy(value_buf, pi->value, len);
+    value_buf[len] = '\0';
+
+    // TODO: see todo in __system_property_read function
+    atomic_thread_fence(memory_order_acquire);
+    if (serial == load_const_atomic(&(pi->serial), memory_order_relaxed)) {
+      callback(cookie, pi->name, value_buf, serial);
+      return;
+    }
+  }
+}
+
+__BIONIC_WEAK_FOR_NATIVE_BRIDGE
+int __system_property_get(const char* name, char* value) {
+  const prop_info* pi = __system_property_find(name);
+
+  if (pi != 0) {
+    return __system_property_read(pi, nullptr, value);
+  } else {
+    value[0] = 0;
+    return 0;
+  }
+}
+
+static constexpr uint32_t kProtocolVersion1 = 1;
+static constexpr uint32_t kProtocolVersion2 = 2;  // current
+
+static atomic_uint_least32_t g_propservice_protocol_version = 0;
+
+static void detect_protocol_version() {
+  char value[PROP_VALUE_MAX];
+  if (__system_property_get(kServiceVersionPropertyName, value) == 0) {
+    g_propservice_protocol_version = kProtocolVersion1;
+    async_safe_format_log(ANDROID_LOG_WARN, "libc",
+                          "Using old property service protocol (\"%s\" is not set)",
+                          kServiceVersionPropertyName);
+  } else {
+    uint32_t version = static_cast<uint32_t>(atoll(value));
+    if (version >= kProtocolVersion2) {
+      g_propservice_protocol_version = kProtocolVersion2;
+    } else {
+      async_safe_format_log(ANDROID_LOG_WARN, "libc",
+                            "Using old property service protocol (\"%s\"=\"%s\")",
+                            kServiceVersionPropertyName, value);
+      g_propservice_protocol_version = kProtocolVersion1;
+    }
+  }
+}
+
+__BIONIC_WEAK_FOR_NATIVE_BRIDGE
+int __system_property_set(const char* key, const char* value) {
+  if (key == nullptr) return -1;
+  if (value == nullptr) value = "";
+
+  if (g_propservice_protocol_version == 0) {
+    detect_protocol_version();
+  }
+
+  if (g_propservice_protocol_version == kProtocolVersion1) {
+    // Old protocol does not support long names or values
+    if (strlen(key) >= PROP_NAME_MAX) return -1;
+    if (strlen(value) >= PROP_VALUE_MAX) return -1;
+
+    prop_msg msg;
+    memset(&msg, 0, sizeof msg);
+    msg.cmd = PROP_MSG_SETPROP;
+    strlcpy(msg.name, key, sizeof msg.name);
+    strlcpy(msg.value, value, sizeof msg.value);
+
+    return send_prop_msg(&msg);
+  } else {
+    // New protocol only allows long values for ro. properties only.
+    if (strlen(value) >= PROP_VALUE_MAX && !is_read_only(key)) return -1;
+    // Use proper protocol
+    PropertyServiceConnection connection;
+    if (!connection.IsValid()) {
+      errno = connection.GetLastError();
+      async_safe_format_log(
+          ANDROID_LOG_WARN, "libc",
+          "Unable to set property \"%s\" to \"%s\": connection failed; errno=%d (%s)", key, value,
+          errno, strerror(errno));
+      return -1;
+    }
+
+    SocketWriter writer(&connection);
+    if (!writer.WriteUint32(PROP_MSG_SETPROP2).WriteString(key).WriteString(value).Send()) {
+      errno = connection.GetLastError();
+      async_safe_format_log(ANDROID_LOG_WARN, "libc",
+                            "Unable to set property \"%s\" to \"%s\": write failed; errno=%d (%s)",
+                            key, value, errno, strerror(errno));
+      return -1;
+    }
+
+    int result = -1;
+    if (!connection.RecvInt32(&result)) {
+      errno = connection.GetLastError();
+      async_safe_format_log(ANDROID_LOG_WARN, "libc",
+                            "Unable to set property \"%s\" to \"%s\": recv failed; errno=%d (%s)",
+                            key, value, errno, strerror(errno));
+      return -1;
+    }
+
+    if (result != PROP_SUCCESS) {
+      async_safe_format_log(ANDROID_LOG_WARN, "libc",
+                            "Unable to set property \"%s\" to \"%s\": error code: 0x%x", key, value,
+                            result);
+      return -1;
+    }
+
+    return 0;
+  }
+}
+
+__BIONIC_WEAK_FOR_NATIVE_BRIDGE
+int __system_property_update(prop_info* pi, const char* value, unsigned int len) {
+  if (len >= PROP_VALUE_MAX) {
+    return -1;
+  }
+
+  if (contexts == nullptr) {
+    return -1;
+  }
+
+  prop_area* pa = contexts->GetSerialPropArea();
+  if (!pa) {
+    return -1;
+  }
+
+  uint32_t serial = atomic_load_explicit(&pi->serial, memory_order_relaxed);
+  serial |= 1;
+  atomic_store_explicit(&pi->serial, serial, memory_order_relaxed);
+  // The memcpy call here also races.  Again pretend it
+  // used memory_order_relaxed atomics, and use the analogous
+  // counterintuitive fence.
+  atomic_thread_fence(memory_order_release);
+  strlcpy(pi->value, value, len + 1);
+
+  atomic_store_explicit(&pi->serial, (len << 24) | ((serial + 1) & 0xffffff), memory_order_release);
+  __futex_wake(&pi->serial, INT32_MAX);
+
+  atomic_store_explicit(pa->serial(), atomic_load_explicit(pa->serial(), memory_order_relaxed) + 1,
+                        memory_order_release);
+  __futex_wake(pa->serial(), INT32_MAX);
+
+  return 0;
+}
+
+__BIONIC_WEAK_FOR_NATIVE_BRIDGE
+int __system_property_add(const char* name, unsigned int namelen, const char* value,
+                          unsigned int valuelen) {
+  if (valuelen >= PROP_VALUE_MAX && !is_read_only(name)) {
+    return -1;
+  }
+
+  if (namelen < 1) {
+    return -1;
+  }
+
+  if (contexts == nullptr) {
+    return -1;
+  }
+
+  prop_area* serial_pa = contexts->GetSerialPropArea();
+  if (serial_pa == nullptr) {
+    return -1;
+  }
+
+  prop_area* pa = contexts->GetPropAreaForName(name);
+  if (!pa) {
+    async_safe_format_log(ANDROID_LOG_ERROR, "libc", "Access denied adding property \"%s\"", name);
+    return -1;
+  }
+
+  bool ret = pa->add(name, namelen, value, valuelen);
+  if (!ret) {
+    return -1;
+  }
+
+  // There is only a single mutator, but we want to make sure that
+  // updates are visible to a reader waiting for the update.
+  atomic_store_explicit(serial_pa->serial(),
+                        atomic_load_explicit(serial_pa->serial(), memory_order_relaxed) + 1,
+                        memory_order_release);
+  __futex_wake(serial_pa->serial(), INT32_MAX);
+  return 0;
+}
+
+// Wait for non-locked serial, and retrieve it with acquire semantics.
+__BIONIC_WEAK_FOR_NATIVE_BRIDGE
+uint32_t __system_property_serial(const prop_info* pi) {
+  uint32_t serial = load_const_atomic(&pi->serial, memory_order_acquire);
+  while (SERIAL_DIRTY(serial)) {
+    __futex_wait(const_cast<_Atomic(uint_least32_t)*>(&pi->serial), serial, nullptr);
+    serial = load_const_atomic(&pi->serial, memory_order_acquire);
+  }
+  return serial;
+}
+
+__BIONIC_WEAK_FOR_NATIVE_BRIDGE
+uint32_t __system_property_wait_any(uint32_t old_serial) {
+  uint32_t new_serial;
+  __system_property_wait(nullptr, old_serial, &new_serial, nullptr);
+  return new_serial;
+}
+
+__BIONIC_WEAK_FOR_NATIVE_BRIDGE
+bool __system_property_wait(const prop_info* pi, uint32_t old_serial, uint32_t* new_serial_ptr,
+                            const timespec* relative_timeout) {
+  // Are we waiting on the global serial or a specific serial?
+  atomic_uint_least32_t* serial_ptr;
+  if (pi == nullptr) {
+    if (contexts == nullptr) {
+      return -1;
+    }
+
+    prop_area* serial_pa = contexts->GetSerialPropArea();
+    if (serial_pa == nullptr) {
+      return -1;
+    }
+
+    serial_ptr = serial_pa->serial();
+  } else {
+    serial_ptr = const_cast<atomic_uint_least32_t*>(&pi->serial);
+  }
+
+  uint32_t new_serial;
+  do {
+    int rc;
+    if ((rc = __futex_wait(serial_ptr, old_serial, relative_timeout)) != 0 && rc == -ETIMEDOUT) {
+      return false;
+    }
+    new_serial = load_const_atomic(serial_ptr, memory_order_acquire);
+  } while (new_serial == old_serial);
+
+  *new_serial_ptr = new_serial;
+  return true;
+}
+
+__BIONIC_WEAK_FOR_NATIVE_BRIDGE
+const prop_info* __system_property_find_nth(unsigned n) {
+  struct find_nth {
+    const uint32_t sought;
+    uint32_t current;
+    const prop_info* result;
+
+    explicit find_nth(uint32_t n) : sought(n), current(0), result(nullptr) {
+    }
+    static void fn(const prop_info* pi, void* ptr) {
+      find_nth* self = reinterpret_cast<find_nth*>(ptr);
+      if (self->current++ == self->sought) self->result = pi;
+    }
+  } state(n);
+  __system_property_foreach(find_nth::fn, &state);
+  return state.result;
+}
+
+__BIONIC_WEAK_FOR_NATIVE_BRIDGE
+int __system_property_foreach(void (*propfn)(const prop_info* pi, void* cookie), void* cookie) {
+  if (contexts == nullptr) {
+    return -1;
+  }
+
+  contexts->ForEach(propfn, cookie);
+
+  return 0;
+}
diff --git a/libc/upstream-freebsd/android/include/freebsd-compat.h b/libc/upstream-freebsd/android/include/freebsd-compat.h
index 8f0a307..e646e23 100644
--- a/libc/upstream-freebsd/android/include/freebsd-compat.h
+++ b/libc/upstream-freebsd/android/include/freebsd-compat.h
@@ -50,6 +50,4 @@
 /* FreeBSD has this, but we can't really implement it correctly on Linux. */
 #define issetugid() 0
 
-#define ARG_MAX sysconf(_SC_ARG_MAX)
-
 #endif
diff --git a/tests/Android.bp b/tests/Android.bp
index 6ec3c3c..c045c1e 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -286,8 +286,9 @@
         "gtest_main.cpp",
         "gtest_globals.cpp",
     ],
-    static_libs: [
+    whole_static_libs: [
         "libbase",
+        "liblog",
     ],
     include_dirs: [
         "bionic/libc",
@@ -354,6 +355,9 @@
         "gtest_main.cpp",
         "gtest_globals_cts.cpp",
     ],
+    static_libs: [
+        "libbase",
+    ],
     cppflags: ["-DUSING_GTEST_OUTPUT_FORMAT"],
     shared: {
         enabled: false,
diff --git a/tests/Android.mk b/tests/Android.mk
index 98216d7..c945bab 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -75,7 +75,7 @@
 
 LOCAL_CLANG := false
 LOCAL_MODULE := bionic-compile-time-tests-g++
-LOCAL_CPPFLAGS := -Wall
+LOCAL_CPPFLAGS := -Wall -Werror
 # Disable color diagnostics so the warnings output matches the source
 LOCAL_CPPFLAGS += -fdiagnostics-color=never
 LOCAL_SRC_FILES := fortify_filecheck_diagnostics_test.cpp
@@ -94,7 +94,7 @@
 
 LOCAL_CLANG := true
 LOCAL_MODULE := bionic-compile-time-tests-clang++
-LOCAL_CPPFLAGS := -Wall
+LOCAL_CPPFLAGS := -Wall -Werror
 LOCAL_CPPFLAGS += -fno-color-diagnostics -ferror-limit=10000
 LOCAL_SRC_FILES := fortify_filecheck_diagnostics_test.cpp
 include $(BUILD_STATIC_LIBRARY)
diff --git a/tests/grp_pwd_test.cpp b/tests/grp_pwd_test.cpp
index 38afee2..61748c8 100644
--- a/tests/grp_pwd_test.cpp
+++ b/tests/grp_pwd_test.cpp
@@ -26,13 +26,17 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <bitset>
+#include <set>
+#include <vector>
 
+#include <android-base/strings.h>
 #include <private/android_filesystem_config.h>
 
 // Generated android_ids array
 #include "generated_android_ids.h"
 
+using android::base::Join;
+
 enum uid_type_t {
   TYPE_SYSTEM,
   TYPE_APP
@@ -186,51 +190,86 @@
   check_get_passwd("u1_i0", 199000, TYPE_APP);
 }
 
+template <typename T>
+static void expect_ids(const T& ids) {
+  std::set<typename T::key_type> expected_ids;
+  // Ensure that all android_ids are iterated through.
+  for (size_t n = 0; n < android_id_count; ++n) {
+    EXPECT_EQ(1U, ids.count(android_ids[n].aid)) << "android_ids[n].aid: " << android_ids[n].aid;
+    expected_ids.emplace(android_ids[n].aid);
+  }
+
+  auto expect_range = [&ids, &expected_ids](uid_t start, uid_t end) {
+    for (size_t n = start; n <= end; ++n) {
+      EXPECT_EQ(1U, ids.count(n)) << "n: " << n;
+      expected_ids.emplace(n);
+    }
+  };
+
+  // Ensure that all reserved ranges are iterated through.
+  expect_range(AID_OEM_RESERVED_START, AID_OEM_RESERVED_END);
+  expect_range(AID_OEM_RESERVED_2_START, AID_OEM_RESERVED_2_END);
+  expect_range(AID_APP_START, AID_APP_END);
+  expect_range(AID_CACHE_GID_START, AID_CACHE_GID_END);
+  expect_range(AID_EXT_GID_START, AID_EXT_GID_END);
+  expect_range(AID_EXT_CACHE_GID_START, AID_EXT_CACHE_GID_END);
+  expect_range(AID_SHARED_GID_START, AID_SHARED_GID_END);
+  expect_range(AID_ISOLATED_START, AID_ISOLATED_END);
+
+  // Ensure that no other ids were returned.
+  auto return_differences = [&ids, &expected_ids] {
+    std::vector<typename T::key_type> missing_from_ids;
+    std::set_difference(expected_ids.begin(), expected_ids.end(), ids.begin(), ids.end(),
+                        std::inserter(missing_from_ids, missing_from_ids.begin()));
+    std::vector<typename T::key_type> extra_in_ids;
+    std::set_difference(ids.begin(), ids.end(), expected_ids.begin(), expected_ids.end(),
+                        std::inserter(extra_in_ids, extra_in_ids.begin()));
+    std::string result;
+    if (!missing_from_ids.empty()) {
+      result += "Missing ids from results: " + Join(missing_from_ids, " ");
+    }
+    if (!extra_in_ids.empty()) {
+      if (!result.empty()) result += ", ";
+      result += "Extra ids in results: " + Join(extra_in_ids, " ");
+    }
+    return result;
+  };
+  EXPECT_EQ(expected_ids, ids) << return_differences();
+}
+
 TEST(pwd, getpwent_iterate) {
   passwd* pwd;
-  std::bitset<10000> exist;
-  bool application = false;
-
-  exist.reset();
+  std::set<uid_t> uids;
 
   setpwent();
   while ((pwd = getpwent()) != NULL) {
     ASSERT_TRUE(NULL != pwd->pw_name);
+
     EXPECT_EQ(pwd->pw_gid, pwd->pw_uid) << "pwd->pw_uid: " << pwd->pw_uid;
     EXPECT_EQ(NULL, pwd->pw_passwd) << "pwd->pw_uid: " << pwd->pw_uid;
 #ifdef __LP64__
     EXPECT_TRUE(NULL == pwd->pw_gecos) << "pwd->pw_uid: " << pwd->pw_uid;
 #endif
     EXPECT_TRUE(NULL != pwd->pw_shell);
-    if (pwd->pw_uid >= exist.size()) {
-      EXPECT_STREQ("/data", pwd->pw_dir) << "pwd->pw_uid: " << pwd->pw_uid;
-      application = true;
-    } else {
+    if (pwd->pw_uid < AID_APP_START || pwd->pw_uid == AID_OVERFLOWUID) {
       EXPECT_STREQ("/", pwd->pw_dir) << "pwd->pw_uid: " << pwd->pw_uid;
-      // TODO(b/27999086): fix this check with the OEM range
-      // If OEMs add their own AIDs to private/android_filesystem_config.h, this check will fail.
-      // Long term we want to create a better solution for OEMs adding AIDs, but we're not there
-      // yet, so therefore we do not check for uid's in the OEM range.
-      if (!(pwd->pw_uid >= 2900 && pwd->pw_uid <= 2999) &&
-          !(pwd->pw_uid >= 5000 && pwd->pw_uid <= 5999)) {
-        EXPECT_FALSE(exist[pwd->pw_uid]) << "pwd->pw_uid: " << pwd->pw_uid;
-      }
-      exist[pwd->pw_uid] = true;
+    } else {
+      EXPECT_STREQ("/data", pwd->pw_dir) << "pwd->pw_uid: " << pwd->pw_uid;
     }
+
+    // TODO(b/27999086): fix this check with the OEM range
+    // If OEMs add their own AIDs to private/android_filesystem_config.h, this check will fail.
+    // Long term we want to create a better solution for OEMs adding AIDs, but we're not there
+    // yet, so therefore we do not check for uid's in the OEM range.
+    if (!(pwd->pw_uid >= 2900 && pwd->pw_uid <= 2999) &&
+        !(pwd->pw_uid >= 5000 && pwd->pw_uid <= 5999)) {
+      EXPECT_EQ(0U, uids.count(pwd->pw_uid)) << "pwd->pw_uid: " << pwd->pw_uid;
+    }
+    uids.emplace(pwd->pw_uid);
   }
   endpwent();
 
-  // Required content
-  for (size_t n = 0; n < android_id_count; ++n) {
-    EXPECT_TRUE(exist[android_ids[n].aid]) << "android_ids[n].aid: " << android_ids[n].aid;
-  }
-  for (size_t n = 2900; n < 2999; ++n) {
-    EXPECT_TRUE(exist[n]) << "n: " << n;
-  }
-  for (size_t n = 5000; n < 5999; ++n) {
-    EXPECT_TRUE(exist[n]) << "n: " << n;
-  }
-  EXPECT_TRUE(application);
+  expect_ids(uids);
 }
 
 static void check_group(const group* grp, const char* group_name, gid_t gid) {
@@ -446,10 +485,7 @@
 
 TEST(grp, getgrent_iterate) {
   group* grp;
-  std::bitset<10000> exist;
-  bool application = false;
-
-  exist.reset();
+  std::set<gid_t> gids;
 
   setgrent();
   while ((grp = getgrent()) != NULL) {
@@ -457,31 +493,18 @@
     ASSERT_TRUE(grp->gr_mem != NULL) << "grp->gr_gid: " << grp->gr_gid;
     EXPECT_STREQ(grp->gr_name, grp->gr_mem[0]) << "grp->gr_gid: " << grp->gr_gid;
     EXPECT_TRUE(grp->gr_mem[1] == NULL) << "grp->gr_gid: " << grp->gr_gid;
-    if (grp->gr_gid >= exist.size()) {
-      application = true;
-    } else {
-      // TODO(b/27999086): fix this check with the OEM range
-      // If OEMs add their own AIDs to private/android_filesystem_config.h, this check will fail.
-      // Long term we want to create a better solution for OEMs adding AIDs, but we're not there
-      // yet, so therefore we do not check for gid's in the OEM range.
-      if (!(grp->gr_gid >= 2900 && grp->gr_gid <= 2999) &&
-          !(grp->gr_gid >= 5000 && grp->gr_gid <= 5999)) {
-        EXPECT_FALSE(exist[grp->gr_gid]) << "grp->gr_gid: " << grp->gr_gid;
-      }
-      exist[grp->gr_gid] = true;
+
+    // TODO(b/27999086): fix this check with the OEM range
+    // If OEMs add their own AIDs to private/android_filesystem_config.h, this check will fail.
+    // Long term we want to create a better solution for OEMs adding AIDs, but we're not there
+    // yet, so therefore we do not check for gid's in the OEM range.
+    if (!(grp->gr_gid >= 2900 && grp->gr_gid <= 2999) &&
+        !(grp->gr_gid >= 5000 && grp->gr_gid <= 5999)) {
+      EXPECT_EQ(0U, gids.count(grp->gr_gid)) << "grp->gr_gid: " << grp->gr_gid;
     }
+    gids.emplace(grp->gr_gid);
   }
   endgrent();
 
-  // Required content
-  for (size_t n = 0; n < android_id_count; ++n) {
-    EXPECT_TRUE(exist[android_ids[n].aid]) << "android_ids[n].aid: " << android_ids[n].aid;
-  }
-  for (size_t n = 2900; n < 2999; ++n) {
-    EXPECT_TRUE(exist[n]) << "n: " << n;
-  }
-  for (size_t n = 5000; n < 5999; ++n) {
-    EXPECT_TRUE(exist[n]) << "n: " << n;
-  }
-  EXPECT_TRUE(application);
+  expect_ids(gids);
 }
diff --git a/tests/gtest_main.cpp b/tests/gtest_main.cpp
index 9dcc000..3f59a9c 100644
--- a/tests/gtest_main.cpp
+++ b/tests/gtest_main.cpp
@@ -23,6 +23,7 @@
 #include <libgen.h>
 #include <limits.h>
 #include <signal.h>
+#include <spawn.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <string.h>
@@ -35,6 +36,10 @@
 #include <utility>
 #include <vector>
 
+#include <android-base/file.h>
+#include <android-base/strings.h>
+#include <android-base/unique_fd.h>
+
 #ifndef TEMP_FAILURE_RETRY
 
 /* Used to retry syscalls that can return EINTR. */
@@ -269,49 +274,61 @@
 }
 
 static bool EnumerateTests(int argc, char** argv, std::vector<TestCase>& testcase_list) {
-  std::string command;
-  for (int i = 0; i < argc; ++i) {
-    command += argv[i];
-    command += " ";
-  }
-  command += "--gtest_list_tests";
-  FILE* fp = popen(command.c_str(), "r");
-  if (fp == NULL) {
-    perror("popen");
+  std::vector<const char*> args;
+  for (int i = 0; i < argc; ++i) args.push_back(argv[i]);
+  args.push_back("--gtest_list_tests");
+  args.push_back(nullptr);
+
+  // We use posix_spawn(3) rather than the simpler popen(3) because we don't want an intervening
+  // surprise shell invocation making quoting interesting for --gtest_filter (http://b/68949647).
+
+  android::base::unique_fd read_fd;
+  android::base::unique_fd write_fd;
+  if (!android::base::Pipe(&read_fd, &write_fd)) {
+    perror("pipe");
     return false;
   }
 
-  char buf[200];
-  while (fgets(buf, sizeof(buf), fp) != NULL) {
-    char* p = buf;
+  posix_spawn_file_actions_t fa;
+  posix_spawn_file_actions_init(&fa);
+  posix_spawn_file_actions_addclose(&fa, read_fd);
+  posix_spawn_file_actions_adddup2(&fa, write_fd, 1);
+  posix_spawn_file_actions_adddup2(&fa, write_fd, 2);
+  posix_spawn_file_actions_addclose(&fa, write_fd);
 
-    while (*p != '\0' && isspace(*p)) {
-      ++p;
-    }
-    if (*p == '\0') continue;
-    char* start = p;
-    while (*p != '\0' && !isspace(*p)) {
-      ++p;
-    }
-    char* end = p;
-    while (*p != '\0' && isspace(*p)) {
-      ++p;
-    }
-    if (*p != '\0' && *p != '#') {
-      // This is not we want, gtest must meet with some error when parsing the arguments.
-      fprintf(stderr, "argument error, check with --help\n");
-      return false;
-    }
-    *end = '\0';
-    if (*(end - 1) == '.') {
-      *(end - 1) = '\0';
-      testcase_list.push_back(TestCase(start));
+  pid_t pid;
+  int result = posix_spawnp(&pid, argv[0], &fa, nullptr, const_cast<char**>(args.data()), nullptr);
+  posix_spawn_file_actions_destroy(&fa);
+  if (result == -1) {
+    perror("posix_spawn");
+    return false;
+  }
+  write_fd.reset();
+
+  std::string content;
+  if (!android::base::ReadFdToString(read_fd, &content)) {
+    perror("ReadFdToString");
+    return false;
+  }
+
+  for (auto& line : android::base::Split(content, "\n")) {
+    line = android::base::Split(line, "#")[0];
+    line = android::base::Trim(line);
+    if (line.empty()) continue;
+    if (android::base::EndsWith(line, ".")) {
+      line.pop_back();
+      testcase_list.push_back(TestCase(line.c_str()));
     } else {
-      testcase_list.back().AppendTest(start);
+      testcase_list.back().AppendTest(line.c_str());
     }
   }
-  int result = pclose(fp);
-  return (result != -1 && WEXITSTATUS(result) == 0);
+
+  int status;
+  if (waitpid(pid, &status, 0) != pid) {
+    perror("waitpid");
+    return false;
+  }
+  return (WIFEXITED(status) && WEXITSTATUS(status) == 0);
 }
 
 // Part of the following *Print functions are copied from external/gtest/src/gtest.cc:
@@ -1249,3 +1266,24 @@
 TEST_F(bionic_selftest_DeathTest, fail) {
   ASSERT_EXIT(deathtest_helper_fail(), ::testing::ExitedWithCode(0), "");
 }
+
+class BionicSelfTest : public ::testing::TestWithParam<bool> {
+};
+
+TEST_P(BionicSelfTest, test_success) {
+  ASSERT_EQ(GetParam(), GetParam());
+}
+
+INSTANTIATE_TEST_CASE_P(bionic_selftest, BionicSelfTest, ::testing::Values(true, false));
+
+template <typename T>
+class bionic_selftest_TestT : public ::testing::Test {
+};
+
+typedef ::testing::Types<char, int> MyTypes;
+
+TYPED_TEST_CASE(bionic_selftest_TestT, MyTypes);
+
+TYPED_TEST(bionic_selftest_TestT, test_success) {
+  ASSERT_EQ(true, true);
+}
diff --git a/tests/libs/Android.mk b/tests/libs/Android.mk
index a54318d..5bd028d 100644
--- a/tests/libs/Android.mk
+++ b/tests/libs/Android.mk
@@ -17,7 +17,7 @@
 LOCAL_PATH := $(call my-dir)
 TEST_PATH := $(LOCAL_PATH)/..
 
-common_cppflags :=
+common_cppflags := -Wall -Werror
 common_additional_dependencies := \
     $(LOCAL_PATH)/Android.mk \
     $(LOCAL_PATH)/Android.build.dt_runpath.mk \
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index 456ddde..022da4d 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -1017,36 +1017,11 @@
 }
 
 TEST(UNISTD_TEST, sysconf_SC_ARG_MAX) {
-  // Since Linux 2.6.23, ARG_MAX isn't a constant and depends on RLIMIT_STACK.
-
-  // Get our current limit, and set things up so we restore the limit.
-  rlimit rl;
-  ASSERT_EQ(0, getrlimit(RLIMIT_STACK, &rl));
-  uint64_t original_rlim_cur = rl.rlim_cur;
-  if (rl.rlim_cur == RLIM_INFINITY) {
-    rl.rlim_cur = 8 * 1024 * 1024; // Bionic reports unlimited stacks as 8MiB.
-  }
-  auto guard = android::base::make_scope_guard([&rl, original_rlim_cur]() {
-    rl.rlim_cur = original_rlim_cur;
-    ASSERT_EQ(0, setrlimit(RLIMIT_STACK, &rl));
-  });
-
-  // _SC_ARG_MAX should be 1/4 the stack size.
-  EXPECT_EQ(static_cast<long>(rl.rlim_cur / 4), sysconf(_SC_ARG_MAX));
-
-  // If you have a really small stack, the kernel still guarantees "32 pages" (fs/exec.c).
-  rl.rlim_cur = 1024;
-  rl.rlim_max = RLIM_INFINITY;
-  ASSERT_EQ(0, setrlimit(RLIMIT_STACK, &rl));
-
-  EXPECT_EQ(static_cast<long>(32 * sysconf(_SC_PAGE_SIZE)), sysconf(_SC_ARG_MAX));
-
-  // With a 128-page stack limit, we know exactly what _SC_ARG_MAX should be...
-  rl.rlim_cur = 128 * sysconf(_SC_PAGE_SIZE);
-  rl.rlim_max = RLIM_INFINITY;
-  ASSERT_EQ(0, setrlimit(RLIMIT_STACK, &rl));
-
-  EXPECT_EQ(static_cast<long>((128 * sysconf(_SC_PAGE_SIZE)) / 4), sysconf(_SC_ARG_MAX));
+  // https://lkml.org/lkml/2017/11/15/813.
+#if !defined(ARG_MAX)
+#define ARG_MAX 131072
+#endif
+  ASSERT_EQ(ARG_MAX, sysconf(_SC_ARG_MAX));
 }
 
 TEST(UNISTD_TEST, dup2_same) {