diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp
index b26db47961..e0b6180c55 100644
--- a/src/common/string_util.cpp
+++ b/src/common/string_util.cpp
@@ -30,7 +30,7 @@ std::string ToUpper(std::string str) {
     return str;
 }
 
-std::string StringFromBuffer(const std::vector<u8>& data) {
+std::string StringFromBuffer(std::span<const u8> data) {
     return std::string(data.begin(), std::find(data.begin(), data.end(), '\0'));
 }
 
diff --git a/src/common/string_util.h b/src/common/string_util.h
index ce18a33cfe..f8aecc875e 100644
--- a/src/common/string_util.h
+++ b/src/common/string_util.h
@@ -5,6 +5,7 @@
 #pragma once
 
 #include <cstddef>
+#include <span>
 #include <string>
 #include <vector>
 #include "common/common_types.h"
@@ -17,7 +18,7 @@ namespace Common {
 /// Make a string uppercase
 [[nodiscard]] std::string ToUpper(std::string str);
 
-[[nodiscard]] std::string StringFromBuffer(const std::vector<u8>& data);
+[[nodiscard]] std::string StringFromBuffer(std::span<const u8> data);
 
 [[nodiscard]] std::string StripSpaces(const std::string& s);
 [[nodiscard]] std::string StripQuotes(const std::string& s);
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index 738b6d0f17..494151eef9 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -11,6 +11,7 @@
 #include "common/common_funcs.h"
 #include "common/common_types.h"
 #include "common/logging/log.h"
+#include "common/scratch_buffer.h"
 #include "core/hle/ipc_helpers.h"
 #include "core/hle/kernel/hle_ipc.h"
 #include "core/hle/kernel/k_auto_object.h"
@@ -325,7 +326,7 @@ Result HLERequestContext::WriteToOutgoingCommandBuffer(KThread& requesting_threa
     return ResultSuccess;
 }
 
-std::vector<u8> HLERequestContext::ReadBuffer(std::size_t buffer_index) const {
+std::vector<u8> HLERequestContext::ReadBufferCopy(std::size_t buffer_index) const {
     const bool is_buffer_a{BufferDescriptorA().size() > buffer_index &&
                            BufferDescriptorA()[buffer_index].Size()};
     if (is_buffer_a) {
@@ -345,6 +346,33 @@ std::vector<u8> HLERequestContext::ReadBuffer(std::size_t buffer_index) const {
     }
 }
 
+std::span<const u8> HLERequestContext::ReadBuffer(std::size_t buffer_index) const {
+    static thread_local std::array<Common::ScratchBuffer<u8>, 2> read_buffer_a;
+    static thread_local std::array<Common::ScratchBuffer<u8>, 2> read_buffer_x;
+
+    const bool is_buffer_a{BufferDescriptorA().size() > buffer_index &&
+                           BufferDescriptorA()[buffer_index].Size()};
+    if (is_buffer_a) {
+        ASSERT_OR_EXECUTE_MSG(
+            BufferDescriptorA().size() > buffer_index, { return {}; },
+            "BufferDescriptorA invalid buffer_index {}", buffer_index);
+        auto& read_buffer = read_buffer_a[buffer_index];
+        read_buffer.resize_destructive(BufferDescriptorA()[buffer_index].Size());
+        memory.ReadBlock(BufferDescriptorA()[buffer_index].Address(), read_buffer.data(),
+                         read_buffer.size());
+        return read_buffer;
+    } else {
+        ASSERT_OR_EXECUTE_MSG(
+            BufferDescriptorX().size() > buffer_index, { return {}; },
+            "BufferDescriptorX invalid buffer_index {}", buffer_index);
+        auto& read_buffer = read_buffer_x[buffer_index];
+        read_buffer.resize_destructive(BufferDescriptorX()[buffer_index].Size());
+        memory.ReadBlock(BufferDescriptorX()[buffer_index].Address(), read_buffer.data(),
+                         read_buffer.size());
+        return read_buffer;
+    }
+}
+
 std::size_t HLERequestContext::WriteBuffer(const void* buffer, std::size_t size,
                                            std::size_t buffer_index) const {
     if (size == 0) {
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h
index e252b5f4b5..5bf4f171bc 100644
--- a/src/core/hle/kernel/hle_ipc.h
+++ b/src/core/hle/kernel/hle_ipc.h
@@ -7,6 +7,7 @@
 #include <functional>
 #include <memory>
 #include <optional>
+#include <span>
 #include <string>
 #include <type_traits>
 #include <vector>
@@ -270,8 +271,11 @@ public:
         return domain_message_header.has_value();
     }
 
-    /// Helper function to read a buffer using the appropriate buffer descriptor
-    [[nodiscard]] std::vector<u8> ReadBuffer(std::size_t buffer_index = 0) const;
+    /// Helper function to get a span of a buffer using the appropriate buffer descriptor
+    [[nodiscard]] std::span<const u8> ReadBuffer(std::size_t buffer_index = 0) const;
+
+    /// Helper function to read a copy of a buffer using the appropriate buffer descriptor
+    [[nodiscard]] std::vector<u8> ReadBufferCopy(std::size_t buffer_index = 0) const;
 
     /// Helper function to write a buffer using the appropriate buffer descriptor
     std::size_t WriteBuffer(const void* buffer, std::size_t size,
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 22999c942f..ebcf6e1642 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -1124,7 +1124,7 @@ void IStorageAccessor::Write(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
 
     const u64 offset{rp.Pop<u64>()};
-    const std::vector<u8> data{ctx.ReadBuffer()};
+    const auto data{ctx.ReadBuffer()};
     const std::size_t size{std::min<u64>(data.size(), backing.GetSize() - offset)};
 
     LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, size);
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp
index 3a1c231b64..0ee28752cb 100644
--- a/src/core/hle/service/audio/audren_u.cpp
+++ b/src/core/hle/service/audio/audren_u.cpp
@@ -112,7 +112,7 @@ private:
     void RequestUpdate(Kernel::HLERequestContext& ctx) {
         LOG_TRACE(Service_Audio, "called");
 
-        std::vector<u8> input{ctx.ReadBuffer(0)};
+        const auto input{ctx.ReadBuffer(0)};
 
         // These buffers are written manually to avoid an issue with WriteBuffer throwing errors for
         // checking size 0. Performance size is 0 for most games.
diff --git a/src/core/hle/service/audio/hwopus.cpp b/src/core/hle/service/audio/hwopus.cpp
index 825fb8bcca..e01f873563 100644
--- a/src/core/hle/service/audio/hwopus.cpp
+++ b/src/core/hle/service/audio/hwopus.cpp
@@ -93,7 +93,7 @@ private:
         ctx.WriteBuffer(samples);
     }
 
-    bool DecodeOpusData(u32& consumed, u32& sample_count, const std::vector<u8>& input,
+    bool DecodeOpusData(u32& consumed, u32& sample_count, std::span<const u8> input,
                         std::vector<opus_int16>& output, u64* out_performance_time) const {
         const auto start_time = std::chrono::steady_clock::now();
         const std::size_t raw_output_sz = output.size() * sizeof(opus_int16);
diff --git a/src/core/hle/service/es/es.cpp b/src/core/hle/service/es/es.cpp
index d183e5829a..fb86868596 100644
--- a/src/core/hle/service/es/es.cpp
+++ b/src/core/hle/service/es/es.cpp
@@ -122,7 +122,7 @@ private:
 
     void ImportTicket(Kernel::HLERequestContext& ctx) {
         const auto ticket = ctx.ReadBuffer();
-        const auto cert = ctx.ReadBuffer(1);
+        [[maybe_unused]] const auto cert = ctx.ReadBuffer(1);
 
         if (ticket.size() < sizeof(Core::Crypto::Ticket)) {
             LOG_ERROR(Service_ETicket, "The input buffer is not large enough!");
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp
index fbb16a7da4..447d624e1c 100644
--- a/src/core/hle/service/filesystem/fsp_srv.cpp
+++ b/src/core/hle/service/filesystem/fsp_srv.cpp
@@ -190,7 +190,7 @@ private:
             return;
         }
 
-        const std::vector<u8> data = ctx.ReadBuffer();
+        const auto data = ctx.ReadBuffer();
 
         ASSERT_MSG(
             static_cast<s64>(data.size()) <= length,
@@ -401,11 +401,8 @@ public:
     }
 
     void RenameFile(Kernel::HLERequestContext& ctx) {
-        std::vector<u8> buffer = ctx.ReadBuffer(0);
-        const std::string src_name = Common::StringFromBuffer(buffer);
-
-        buffer = ctx.ReadBuffer(1);
-        const std::string dst_name = Common::StringFromBuffer(buffer);
+        const std::string src_name = Common::StringFromBuffer(ctx.ReadBuffer(0));
+        const std::string dst_name = Common::StringFromBuffer(ctx.ReadBuffer(1));
 
         LOG_DEBUG(Service_FS, "called. file '{}' to file '{}'", src_name, dst_name);
 
@@ -1086,7 +1083,7 @@ void FSP_SRV::GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) {
 }
 
 void FSP_SRV::OutputAccessLogToSdCard(Kernel::HLERequestContext& ctx) {
-    const auto raw = ctx.ReadBuffer();
+    const auto raw = ctx.ReadBufferCopy();
     auto log = Common::StringFromFixedZeroTerminatedBuffer(
         reinterpret_cast<const char*>(raw.data()), raw.size());
 
diff --git a/src/core/hle/service/glue/arp.cpp b/src/core/hle/service/glue/arp.cpp
index 49b6d45fe9..ce21b69e3a 100644
--- a/src/core/hle/service/glue/arp.cpp
+++ b/src/core/hle/service/glue/arp.cpp
@@ -228,7 +228,8 @@ private:
             return;
         }
 
-        control = ctx.ReadBuffer();
+        // TODO: Can this be a span?
+        control = ctx.ReadBufferCopy();
 
         IPC::ResponseBuilder rb{ctx, 2};
         rb.Push(ResultSuccess);
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 3afda9e3f9..513ea485a4 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -758,11 +758,12 @@ Core::HID::NpadStyleTag Controller_NPad::GetSupportedStyleSet() const {
     return hid_core.GetSupportedStyleTag();
 }
 
-void Controller_NPad::SetSupportedNpadIdTypes(u8* data, std::size_t length) {
+void Controller_NPad::SetSupportedNpadIdTypes(std::span<const u8> data) {
+    const auto length = data.size();
     ASSERT(length > 0 && (length % sizeof(u32)) == 0);
     supported_npad_id_types.clear();
     supported_npad_id_types.resize(length / sizeof(u32));
-    std::memcpy(supported_npad_id_types.data(), data, length);
+    std::memcpy(supported_npad_id_types.data(), data.data(), length);
 }
 
 void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) {
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index 1a589cca22..1f7d334595 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -6,6 +6,7 @@
 #include <array>
 #include <atomic>
 #include <mutex>
+#include <span>
 
 #include "common/bit_field.h"
 #include "common/common_types.h"
@@ -95,7 +96,7 @@ public:
     void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set);
     Core::HID::NpadStyleTag GetSupportedStyleSet() const;
 
-    void SetSupportedNpadIdTypes(u8* data, std::size_t length);
+    void SetSupportedNpadIdTypes(std::span<const u8> data);
     void GetSupportedNpadIdTypes(u32* data, std::size_t max_length);
     std::size_t GetSupportedNpadIdTypesSize() const;
 
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index bf28440c62..f15f1a6bb8 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -1026,7 +1026,7 @@ void Hid::SetSupportedNpadIdType(Kernel::HLERequestContext& ctx) {
     const auto applet_resource_user_id{rp.Pop<u64>()};
 
     applet_resource->GetController<Controller_NPad>(HidController::NPad)
-        .SetSupportedNpadIdTypes(ctx.ReadBuffer().data(), ctx.GetReadBufferSize());
+        .SetSupportedNpadIdTypes(ctx.ReadBuffer());
 
     LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
 
@@ -2104,7 +2104,7 @@ void Hid::WritePalmaRgbLedPatternEntry(Kernel::HLERequestContext& ctx) {
     const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
     const auto unknown{rp.Pop<u64>()};
 
-    const auto buffer = ctx.ReadBuffer();
+    [[maybe_unused]] const auto buffer = ctx.ReadBuffer();
 
     LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, unknown={}",
                 connection_handle.npad_id, unknown);
diff --git a/src/core/hle/service/hid/hidbus/hidbus_base.h b/src/core/hle/service/hid/hidbus/hidbus_base.h
index d3960f506d..65e3011378 100644
--- a/src/core/hle/service/hid/hidbus/hidbus_base.h
+++ b/src/core/hle/service/hid/hidbus/hidbus_base.h
@@ -4,6 +4,7 @@
 #pragma once
 
 #include <array>
+#include <span>
 #include "common/common_types.h"
 #include "core/hle/result.h"
 
@@ -150,7 +151,7 @@ public:
     }
 
     // Assigns a command from data
-    virtual bool SetCommand(const std::vector<u8>& data) {
+    virtual bool SetCommand(std::span<const u8> data) {
         return {};
     }
 
diff --git a/src/core/hle/service/hid/hidbus/ringcon.cpp b/src/core/hle/service/hid/hidbus/ringcon.cpp
index 78ed470144..35847cbddc 100644
--- a/src/core/hle/service/hid/hidbus/ringcon.cpp
+++ b/src/core/hle/service/hid/hidbus/ringcon.cpp
@@ -116,7 +116,7 @@ std::vector<u8> RingController::GetReply() const {
     }
 }
 
-bool RingController::SetCommand(const std::vector<u8>& data) {
+bool RingController::SetCommand(std::span<const u8> data) {
     if (data.size() < 4) {
         LOG_ERROR(Service_HID, "Command size not supported {}", data.size());
         command = RingConCommands::Error;
diff --git a/src/core/hle/service/hid/hidbus/ringcon.h b/src/core/hle/service/hid/hidbus/ringcon.h
index 845ce85a5b..c2fb386b13 100644
--- a/src/core/hle/service/hid/hidbus/ringcon.h
+++ b/src/core/hle/service/hid/hidbus/ringcon.h
@@ -4,6 +4,7 @@
 #pragma once
 
 #include <array>
+#include <span>
 
 #include "common/common_types.h"
 #include "core/hle/service/hid/hidbus/hidbus_base.h"
@@ -31,7 +32,7 @@ public:
     u8 GetDeviceId() const override;
 
     // Assigns a command from data
-    bool SetCommand(const std::vector<u8>& data) override;
+    bool SetCommand(std::span<const u8> data) override;
 
     // Returns a reply from a command
     std::vector<u8> GetReply() const override;
diff --git a/src/core/hle/service/hid/hidbus/starlink.cpp b/src/core/hle/service/hid/hidbus/starlink.cpp
index dd439f60af..d0e7603142 100644
--- a/src/core/hle/service/hid/hidbus/starlink.cpp
+++ b/src/core/hle/service/hid/hidbus/starlink.cpp
@@ -42,7 +42,7 @@ std::vector<u8> Starlink::GetReply() const {
     return {};
 }
 
-bool Starlink::SetCommand(const std::vector<u8>& data) {
+bool Starlink::SetCommand(std::span<const u8> data) {
     LOG_ERROR(Service_HID, "Command not implemented");
     return false;
 }
diff --git a/src/core/hle/service/hid/hidbus/starlink.h b/src/core/hle/service/hid/hidbus/starlink.h
index 0b1b7ba499..07c800e6ed 100644
--- a/src/core/hle/service/hid/hidbus/starlink.h
+++ b/src/core/hle/service/hid/hidbus/starlink.h
@@ -29,7 +29,7 @@ public:
     u8 GetDeviceId() const override;
 
     // Assigns a command from data
-    bool SetCommand(const std::vector<u8>& data) override;
+    bool SetCommand(std::span<const u8> data) override;
 
     // Returns a reply from a command
     std::vector<u8> GetReply() const override;
diff --git a/src/core/hle/service/hid/hidbus/stubbed.cpp b/src/core/hle/service/hid/hidbus/stubbed.cpp
index e477443e30..07632c8721 100644
--- a/src/core/hle/service/hid/hidbus/stubbed.cpp
+++ b/src/core/hle/service/hid/hidbus/stubbed.cpp
@@ -43,7 +43,7 @@ std::vector<u8> HidbusStubbed::GetReply() const {
     return {};
 }
 
-bool HidbusStubbed::SetCommand(const std::vector<u8>& data) {
+bool HidbusStubbed::SetCommand(std::span<const u8> data) {
     LOG_ERROR(Service_HID, "Command not implemented");
     return false;
 }
diff --git a/src/core/hle/service/hid/hidbus/stubbed.h b/src/core/hle/service/hid/hidbus/stubbed.h
index 91165ceff9..38eaa0ecc3 100644
--- a/src/core/hle/service/hid/hidbus/stubbed.h
+++ b/src/core/hle/service/hid/hidbus/stubbed.h
@@ -29,7 +29,7 @@ public:
     u8 GetDeviceId() const override;
 
     // Assigns a command from data
-    bool SetCommand(const std::vector<u8>& data) override;
+    bool SetCommand(std::span<const u8> data) override;
 
     // Returns a reply from a command
     std::vector<u8> GetReply() const override;
diff --git a/src/core/hle/service/jit/jit.cpp b/src/core/hle/service/jit/jit.cpp
index 8f2920c515..1295a44c76 100644
--- a/src/core/hle/service/jit/jit.cpp
+++ b/src/core/hle/service/jit/jit.cpp
@@ -62,7 +62,7 @@ public:
         const auto parameters{rp.PopRaw<InputParameters>()};
 
         // Optional input/output buffers
-        std::vector<u8> input_buffer{ctx.CanReadBuffer() ? ctx.ReadBuffer() : std::vector<u8>()};
+        const auto input_buffer{ctx.CanReadBuffer() ? ctx.ReadBuffer() : std::span<const u8>()};
         std::vector<u8> output_buffer(ctx.CanWriteBuffer() ? ctx.GetWriteBufferSize() : 0);
 
         // Function call prototype:
@@ -132,7 +132,7 @@ public:
         const auto command{rp.PopRaw<u64>()};
 
         // Optional input/output buffers
-        std::vector<u8> input_buffer{ctx.CanReadBuffer() ? ctx.ReadBuffer() : std::vector<u8>()};
+        const auto input_buffer{ctx.CanReadBuffer() ? ctx.ReadBuffer() : std::span<const u8>()};
         std::vector<u8> output_buffer(ctx.CanWriteBuffer() ? ctx.GetWriteBufferSize() : 0);
 
         // Function call prototype:
diff --git a/src/core/hle/service/ldn/ldn.cpp b/src/core/hle/service/ldn/ldn.cpp
index c49c61cff4..e5099d61f1 100644
--- a/src/core/hle/service/ldn/ldn.cpp
+++ b/src/core/hle/service/ldn/ldn.cpp
@@ -412,7 +412,7 @@ public:
     }
 
     void SetAdvertiseData(Kernel::HLERequestContext& ctx) {
-        std::vector<u8> read_buffer = ctx.ReadBuffer();
+        const auto read_buffer = ctx.ReadBuffer();
 
         IPC::ResponseBuilder rb{ctx, 2};
         rb.Push(lan_discovery.SetAdvertiseData(read_buffer));
@@ -464,7 +464,7 @@ public:
                  parameters.security_config.passphrase_size,
                  parameters.security_config.security_mode, parameters.local_communication_version);
 
-        const std::vector<u8> read_buffer = ctx.ReadBuffer();
+        const auto read_buffer = ctx.ReadBuffer();
         if (read_buffer.size() != sizeof(NetworkInfo)) {
             LOG_ERROR(Frontend, "NetworkInfo doesn't match read_buffer size!");
             IPC::ResponseBuilder rb{ctx, 2};
diff --git a/src/core/hle/service/nvdrv/devices/nvdevice.h b/src/core/hle/service/nvdrv/devices/nvdevice.h
index 204b0e7572..c562e04d21 100644
--- a/src/core/hle/service/nvdrv/devices/nvdevice.h
+++ b/src/core/hle/service/nvdrv/devices/nvdevice.h
@@ -3,7 +3,9 @@
 
 #pragma once
 
+#include <span>
 #include <vector>
+
 #include "common/common_types.h"
 #include "core/hle/service/nvdrv/nvdata.h"
 
@@ -31,7 +33,7 @@ public:
      * @param output A buffer where the output data will be written to.
      * @returns The result code of the ioctl.
      */
-    virtual NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
+    virtual NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
                             std::vector<u8>& output) = 0;
 
     /**
@@ -42,8 +44,8 @@ public:
      * @param output A buffer where the output data will be written to.
      * @returns The result code of the ioctl.
      */
-    virtual NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
-                            const std::vector<u8>& inline_input, std::vector<u8>& output) = 0;
+    virtual NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
+                            std::span<const u8> inline_input, std::vector<u8>& output) = 0;
 
     /**
      * Handles an ioctl3 request.
@@ -53,7 +55,7 @@ public:
      * @param inline_output A buffer where the inlined output data will be written to.
      * @returns The result code of the ioctl.
      */
-    virtual NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
+    virtual NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input,
                             std::vector<u8>& output, std::vector<u8>& inline_output) = 0;
 
     /**
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
index 4122fc98de..5a5b2e3055 100644
--- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
@@ -17,19 +17,19 @@ nvdisp_disp0::nvdisp_disp0(Core::System& system_, NvCore::Container& core)
     : nvdevice{system_}, container{core}, nvmap{core.GetNvMapFile()} {}
 nvdisp_disp0::~nvdisp_disp0() = default;
 
-NvResult nvdisp_disp0::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
+NvResult nvdisp_disp0::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
                               std::vector<u8>& output) {
     UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
     return NvResult::NotImplemented;
 }
 
-NvResult nvdisp_disp0::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
-                              const std::vector<u8>& inline_input, std::vector<u8>& output) {
+NvResult nvdisp_disp0::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
+                              std::span<const u8> inline_input, std::vector<u8>& output) {
     UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
     return NvResult::NotImplemented;
 }
 
-NvResult nvdisp_disp0::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
+NvResult nvdisp_disp0::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input,
                               std::vector<u8>& output, std::vector<u8>& inline_output) {
     UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
     return NvResult::NotImplemented;
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h
index 04217ab129..81bd7960ad 100644
--- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h
+++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h
@@ -25,12 +25,12 @@ public:
     explicit nvdisp_disp0(Core::System& system_, NvCore::Container& core);
     ~nvdisp_disp0() override;
 
-    NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
+    NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
                     std::vector<u8>& output) override;
-    NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
-                    const std::vector<u8>& inline_input, std::vector<u8>& output) override;
-    NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
-                    std::vector<u8>& output, std::vector<u8>& inline_output) override;
+    NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
+                    std::span<const u8> inline_input, std::vector<u8>& output) override;
+    NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output,
+                    std::vector<u8>& inline_output) override;
 
     void OnOpen(DeviceFD fd) override;
     void OnClose(DeviceFD fd) override;
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
index b635e6ed13..681bd08673 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
@@ -27,7 +27,7 @@ nvhost_as_gpu::nvhost_as_gpu(Core::System& system_, Module& module_, NvCore::Con
 
 nvhost_as_gpu::~nvhost_as_gpu() = default;
 
-NvResult nvhost_as_gpu::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
+NvResult nvhost_as_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
                                std::vector<u8>& output) {
     switch (command.group) {
     case 'A':
@@ -60,13 +60,13 @@ NvResult nvhost_as_gpu::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>
     return NvResult::NotImplemented;
 }
 
-NvResult nvhost_as_gpu::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
-                               const std::vector<u8>& inline_input, std::vector<u8>& output) {
+NvResult nvhost_as_gpu::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
+                               std::span<const u8> inline_input, std::vector<u8>& output) {
     UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
     return NvResult::NotImplemented;
 }
 
-NvResult nvhost_as_gpu::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
+NvResult nvhost_as_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input,
                                std::vector<u8>& output, std::vector<u8>& inline_output) {
     switch (command.group) {
     case 'A':
@@ -87,7 +87,7 @@ NvResult nvhost_as_gpu::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>
 void nvhost_as_gpu::OnOpen(DeviceFD fd) {}
 void nvhost_as_gpu::OnClose(DeviceFD fd) {}
 
-NvResult nvhost_as_gpu::AllocAsEx(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvhost_as_gpu::AllocAsEx(std::span<const u8> input, std::vector<u8>& output) {
     IoctlAllocAsEx params{};
     std::memcpy(&params, input.data(), input.size());
 
@@ -141,7 +141,7 @@ NvResult nvhost_as_gpu::AllocAsEx(const std::vector<u8>& input, std::vector<u8>&
     return NvResult::Success;
 }
 
-NvResult nvhost_as_gpu::AllocateSpace(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvhost_as_gpu::AllocateSpace(std::span<const u8> input, std::vector<u8>& output) {
     IoctlAllocSpace params{};
     std::memcpy(&params, input.data(), input.size());
 
@@ -220,7 +220,7 @@ void nvhost_as_gpu::FreeMappingLocked(u64 offset) {
     mapping_map.erase(offset);
 }
 
-NvResult nvhost_as_gpu::FreeSpace(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvhost_as_gpu::FreeSpace(std::span<const u8> input, std::vector<u8>& output) {
     IoctlFreeSpace params{};
     std::memcpy(&params, input.data(), input.size());
 
@@ -266,7 +266,7 @@ NvResult nvhost_as_gpu::FreeSpace(const std::vector<u8>& input, std::vector<u8>&
     return NvResult::Success;
 }
 
-NvResult nvhost_as_gpu::Remap(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvhost_as_gpu::Remap(std::span<const u8> input, std::vector<u8>& output) {
     const auto num_entries = input.size() / sizeof(IoctlRemapEntry);
 
     LOG_DEBUG(Service_NVDRV, "called, num_entries=0x{:X}", num_entries);
@@ -320,7 +320,7 @@ NvResult nvhost_as_gpu::Remap(const std::vector<u8>& input, std::vector<u8>& out
     return NvResult::Success;
 }
 
-NvResult nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvhost_as_gpu::MapBufferEx(std::span<const u8> input, std::vector<u8>& output) {
     IoctlMapBufferEx params{};
     std::memcpy(&params, input.data(), input.size());
 
@@ -424,7 +424,7 @@ NvResult nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8
     return NvResult::Success;
 }
 
-NvResult nvhost_as_gpu::UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvhost_as_gpu::UnmapBuffer(std::span<const u8> input, std::vector<u8>& output) {
     IoctlUnmapBuffer params{};
     std::memcpy(&params, input.data(), input.size());
 
@@ -463,7 +463,7 @@ NvResult nvhost_as_gpu::UnmapBuffer(const std::vector<u8>& input, std::vector<u8
     return NvResult::Success;
 }
 
-NvResult nvhost_as_gpu::BindChannel(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvhost_as_gpu::BindChannel(std::span<const u8> input, std::vector<u8>& output) {
     IoctlBindChannel params{};
     std::memcpy(&params, input.data(), input.size());
     LOG_DEBUG(Service_NVDRV, "called, fd={:X}", params.fd);
@@ -492,7 +492,7 @@ void nvhost_as_gpu::GetVARegionsImpl(IoctlGetVaRegions& params) {
     };
 }
 
-NvResult nvhost_as_gpu::GetVARegions(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvhost_as_gpu::GetVARegions(std::span<const u8> input, std::vector<u8>& output) {
     IoctlGetVaRegions params{};
     std::memcpy(&params, input.data(), input.size());
 
@@ -511,7 +511,7 @@ NvResult nvhost_as_gpu::GetVARegions(const std::vector<u8>& input, std::vector<u
     return NvResult::Success;
 }
 
-NvResult nvhost_as_gpu::GetVARegions(const std::vector<u8>& input, std::vector<u8>& output,
+NvResult nvhost_as_gpu::GetVARegions(std::span<const u8> input, std::vector<u8>& output,
                                      std::vector<u8>& inline_output) {
     IoctlGetVaRegions params{};
     std::memcpy(&params, input.data(), input.size());
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h
index 86fe71c750..1aba8d5799 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h
@@ -47,12 +47,12 @@ public:
     explicit nvhost_as_gpu(Core::System& system_, Module& module, NvCore::Container& core);
     ~nvhost_as_gpu() override;
 
-    NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
+    NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
                     std::vector<u8>& output) override;
-    NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
-                    const std::vector<u8>& inline_input, std::vector<u8>& output) override;
-    NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
-                    std::vector<u8>& output, std::vector<u8>& inline_output) override;
+    NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
+                    std::span<const u8> inline_input, std::vector<u8>& output) override;
+    NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output,
+                    std::vector<u8>& inline_output) override;
 
     void OnOpen(DeviceFD fd) override;
     void OnClose(DeviceFD fd) override;
@@ -138,17 +138,17 @@ private:
     static_assert(sizeof(IoctlGetVaRegions) == 16 + sizeof(VaRegion) * 2,
                   "IoctlGetVaRegions is incorrect size");
 
-    NvResult AllocAsEx(const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult AllocateSpace(const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult Remap(const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult FreeSpace(const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult BindChannel(const std::vector<u8>& input, std::vector<u8>& output);
+    NvResult AllocAsEx(std::span<const u8> input, std::vector<u8>& output);
+    NvResult AllocateSpace(std::span<const u8> input, std::vector<u8>& output);
+    NvResult Remap(std::span<const u8> input, std::vector<u8>& output);
+    NvResult MapBufferEx(std::span<const u8> input, std::vector<u8>& output);
+    NvResult UnmapBuffer(std::span<const u8> input, std::vector<u8>& output);
+    NvResult FreeSpace(std::span<const u8> input, std::vector<u8>& output);
+    NvResult BindChannel(std::span<const u8> input, std::vector<u8>& output);
 
     void GetVARegionsImpl(IoctlGetVaRegions& params);
-    NvResult GetVARegions(const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult GetVARegions(const std::vector<u8>& input, std::vector<u8>& output,
+    NvResult GetVARegions(std::span<const u8> input, std::vector<u8>& output);
+    NvResult GetVARegions(std::span<const u8> input, std::vector<u8>& output,
                           std::vector<u8>& inline_output);
 
     void FreeMappingLocked(u64 offset);
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
index eee11fab88..0cdde82a71 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
@@ -34,7 +34,7 @@ nvhost_ctrl::~nvhost_ctrl() {
     }
 }
 
-NvResult nvhost_ctrl::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
+NvResult nvhost_ctrl::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
                              std::vector<u8>& output) {
     switch (command.group) {
     case 0x0:
@@ -63,13 +63,13 @@ NvResult nvhost_ctrl::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>&
     return NvResult::NotImplemented;
 }
 
-NvResult nvhost_ctrl::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
-                             const std::vector<u8>& inline_input, std::vector<u8>& output) {
+NvResult nvhost_ctrl::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
+                             std::span<const u8> inline_input, std::vector<u8>& output) {
     UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
     return NvResult::NotImplemented;
 }
 
-NvResult nvhost_ctrl::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
+NvResult nvhost_ctrl::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input,
                              std::vector<u8>& output, std::vector<u8>& inline_outpu) {
     UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
     return NvResult::NotImplemented;
@@ -79,7 +79,7 @@ void nvhost_ctrl::OnOpen(DeviceFD fd) {}
 
 void nvhost_ctrl::OnClose(DeviceFD fd) {}
 
-NvResult nvhost_ctrl::NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvhost_ctrl::NvOsGetConfigU32(std::span<const u8> input, std::vector<u8>& output) {
     IocGetConfigParams params{};
     std::memcpy(&params, input.data(), sizeof(params));
     LOG_TRACE(Service_NVDRV, "called, setting={}!{}", params.domain_str.data(),
@@ -87,7 +87,7 @@ NvResult nvhost_ctrl::NvOsGetConfigU32(const std::vector<u8>& input, std::vector
     return NvResult::ConfigVarNotFound; // Returns error on production mode
 }
 
-NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output,
+NvResult nvhost_ctrl::IocCtrlEventWait(std::span<const u8> input, std::vector<u8>& output,
                                        bool is_allocation) {
     IocCtrlEventWaitParams params{};
     std::memcpy(&params, input.data(), sizeof(params));
@@ -231,7 +231,7 @@ NvResult nvhost_ctrl::FreeEvent(u32 slot) {
     return NvResult::Success;
 }
 
-NvResult nvhost_ctrl::IocCtrlEventRegister(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvhost_ctrl::IocCtrlEventRegister(std::span<const u8> input, std::vector<u8>& output) {
     IocCtrlEventRegisterParams params{};
     std::memcpy(&params, input.data(), sizeof(params));
     const u32 event_id = params.user_event_id;
@@ -252,8 +252,7 @@ NvResult nvhost_ctrl::IocCtrlEventRegister(const std::vector<u8>& input, std::ve
     return NvResult::Success;
 }
 
-NvResult nvhost_ctrl::IocCtrlEventUnregister(const std::vector<u8>& input,
-                                             std::vector<u8>& output) {
+NvResult nvhost_ctrl::IocCtrlEventUnregister(std::span<const u8> input, std::vector<u8>& output) {
     IocCtrlEventUnregisterParams params{};
     std::memcpy(&params, input.data(), sizeof(params));
     const u32 event_id = params.user_event_id & 0x00FF;
@@ -263,7 +262,7 @@ NvResult nvhost_ctrl::IocCtrlEventUnregister(const std::vector<u8>& input,
     return FreeEvent(event_id);
 }
 
-NvResult nvhost_ctrl::IocCtrlEventUnregisterBatch(const std::vector<u8>& input,
+NvResult nvhost_ctrl::IocCtrlEventUnregisterBatch(std::span<const u8> input,
                                                   std::vector<u8>& output) {
     IocCtrlEventUnregisterBatchParams params{};
     std::memcpy(&params, input.data(), sizeof(params));
@@ -282,7 +281,7 @@ NvResult nvhost_ctrl::IocCtrlEventUnregisterBatch(const std::vector<u8>& input,
     return NvResult::Success;
 }
 
-NvResult nvhost_ctrl::IocCtrlClearEventWait(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvhost_ctrl::IocCtrlClearEventWait(std::span<const u8> input, std::vector<u8>& output) {
     IocCtrlEventClearParams params{};
     std::memcpy(&params, input.data(), sizeof(params));
 
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h
index 0b56d70708..dd2e7888af 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h
@@ -25,12 +25,12 @@ public:
                          NvCore::Container& core);
     ~nvhost_ctrl() override;
 
-    NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
+    NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
                     std::vector<u8>& output) override;
-    NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
-                    const std::vector<u8>& inline_input, std::vector<u8>& output) override;
-    NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
-                    std::vector<u8>& output, std::vector<u8>& inline_output) override;
+    NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
+                    std::span<const u8> inline_input, std::vector<u8>& output) override;
+    NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output,
+                    std::vector<u8>& inline_output) override;
 
     void OnOpen(DeviceFD fd) override;
     void OnClose(DeviceFD fd) override;
@@ -186,13 +186,13 @@ private:
     static_assert(sizeof(IocCtrlEventUnregisterBatchParams) == 8,
                   "IocCtrlEventKill is incorrect size");
 
-    NvResult NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output,
+    NvResult NvOsGetConfigU32(std::span<const u8> input, std::vector<u8>& output);
+    NvResult IocCtrlEventWait(std::span<const u8> input, std::vector<u8>& output,
                               bool is_allocation);
-    NvResult IocCtrlEventRegister(const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult IocCtrlEventUnregister(const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult IocCtrlEventUnregisterBatch(const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult IocCtrlClearEventWait(const std::vector<u8>& input, std::vector<u8>& output);
+    NvResult IocCtrlEventRegister(std::span<const u8> input, std::vector<u8>& output);
+    NvResult IocCtrlEventUnregister(std::span<const u8> input, std::vector<u8>& output);
+    NvResult IocCtrlEventUnregisterBatch(std::span<const u8> input, std::vector<u8>& output);
+    NvResult IocCtrlClearEventWait(std::span<const u8> input, std::vector<u8>& output);
 
     NvResult FreeEvent(u32 slot);
 
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
index b97813fbc7..be3c083dbf 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
@@ -21,7 +21,7 @@ nvhost_ctrl_gpu::~nvhost_ctrl_gpu() {
     events_interface.FreeEvent(unknown_event);
 }
 
-NvResult nvhost_ctrl_gpu::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
+NvResult nvhost_ctrl_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
                                  std::vector<u8>& output) {
     switch (command.group) {
     case 'G':
@@ -53,13 +53,13 @@ NvResult nvhost_ctrl_gpu::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u
     return NvResult::NotImplemented;
 }
 
-NvResult nvhost_ctrl_gpu::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
-                                 const std::vector<u8>& inline_input, std::vector<u8>& output) {
+NvResult nvhost_ctrl_gpu::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
+                                 std::span<const u8> inline_input, std::vector<u8>& output) {
     UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
     return NvResult::NotImplemented;
 }
 
-NvResult nvhost_ctrl_gpu::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
+NvResult nvhost_ctrl_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input,
                                  std::vector<u8>& output, std::vector<u8>& inline_output) {
     switch (command.group) {
     case 'G':
@@ -82,8 +82,7 @@ NvResult nvhost_ctrl_gpu::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u
 void nvhost_ctrl_gpu::OnOpen(DeviceFD fd) {}
 void nvhost_ctrl_gpu::OnClose(DeviceFD fd) {}
 
-NvResult nvhost_ctrl_gpu::GetCharacteristics(const std::vector<u8>& input,
-                                             std::vector<u8>& output) {
+NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span<const u8> input, std::vector<u8>& output) {
     LOG_DEBUG(Service_NVDRV, "called");
     IoctlCharacteristics params{};
     std::memcpy(&params, input.data(), input.size());
@@ -128,7 +127,7 @@ NvResult nvhost_ctrl_gpu::GetCharacteristics(const std::vector<u8>& input,
     return NvResult::Success;
 }
 
-NvResult nvhost_ctrl_gpu::GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output,
+NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span<const u8> input, std::vector<u8>& output,
                                              std::vector<u8>& inline_output) {
     LOG_DEBUG(Service_NVDRV, "called");
     IoctlCharacteristics params{};
@@ -176,7 +175,7 @@ NvResult nvhost_ctrl_gpu::GetCharacteristics(const std::vector<u8>& input, std::
     return NvResult::Success;
 }
 
-NvResult nvhost_ctrl_gpu::GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvhost_ctrl_gpu::GetTPCMasks(std::span<const u8> input, std::vector<u8>& output) {
     IoctlGpuGetTpcMasksArgs params{};
     std::memcpy(&params, input.data(), input.size());
     LOG_DEBUG(Service_NVDRV, "called, mask_buffer_size=0x{:X}", params.mask_buffer_size);
@@ -187,7 +186,7 @@ NvResult nvhost_ctrl_gpu::GetTPCMasks(const std::vector<u8>& input, std::vector<
     return NvResult::Success;
 }
 
-NvResult nvhost_ctrl_gpu::GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output,
+NvResult nvhost_ctrl_gpu::GetTPCMasks(std::span<const u8> input, std::vector<u8>& output,
                                       std::vector<u8>& inline_output) {
     IoctlGpuGetTpcMasksArgs params{};
     std::memcpy(&params, input.data(), input.size());
@@ -200,7 +199,7 @@ NvResult nvhost_ctrl_gpu::GetTPCMasks(const std::vector<u8>& input, std::vector<
     return NvResult::Success;
 }
 
-NvResult nvhost_ctrl_gpu::GetActiveSlotMask(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvhost_ctrl_gpu::GetActiveSlotMask(std::span<const u8> input, std::vector<u8>& output) {
     LOG_DEBUG(Service_NVDRV, "called");
 
     IoctlActiveSlotMask params{};
@@ -213,7 +212,7 @@ NvResult nvhost_ctrl_gpu::GetActiveSlotMask(const std::vector<u8>& input, std::v
     return NvResult::Success;
 }
 
-NvResult nvhost_ctrl_gpu::ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvhost_ctrl_gpu::ZCullGetCtxSize(std::span<const u8> input, std::vector<u8>& output) {
     LOG_DEBUG(Service_NVDRV, "called");
 
     IoctlZcullGetCtxSize params{};
@@ -225,7 +224,7 @@ NvResult nvhost_ctrl_gpu::ZCullGetCtxSize(const std::vector<u8>& input, std::vec
     return NvResult::Success;
 }
 
-NvResult nvhost_ctrl_gpu::ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvhost_ctrl_gpu::ZCullGetInfo(std::span<const u8> input, std::vector<u8>& output) {
     LOG_DEBUG(Service_NVDRV, "called");
 
     IoctlNvgpuGpuZcullGetInfoArgs params{};
@@ -248,7 +247,7 @@ NvResult nvhost_ctrl_gpu::ZCullGetInfo(const std::vector<u8>& input, std::vector
     return NvResult::Success;
 }
 
-NvResult nvhost_ctrl_gpu::ZBCSetTable(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvhost_ctrl_gpu::ZBCSetTable(std::span<const u8> input, std::vector<u8>& output) {
     LOG_WARNING(Service_NVDRV, "(STUBBED) called");
 
     IoctlZbcSetTable params{};
@@ -264,7 +263,7 @@ NvResult nvhost_ctrl_gpu::ZBCSetTable(const std::vector<u8>& input, std::vector<
     return NvResult::Success;
 }
 
-NvResult nvhost_ctrl_gpu::ZBCQueryTable(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvhost_ctrl_gpu::ZBCQueryTable(std::span<const u8> input, std::vector<u8>& output) {
     LOG_WARNING(Service_NVDRV, "(STUBBED) called");
 
     IoctlZbcQueryTable params{};
@@ -274,7 +273,7 @@ NvResult nvhost_ctrl_gpu::ZBCQueryTable(const std::vector<u8>& input, std::vecto
     return NvResult::Success;
 }
 
-NvResult nvhost_ctrl_gpu::FlushL2(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvhost_ctrl_gpu::FlushL2(std::span<const u8> input, std::vector<u8>& output) {
     LOG_WARNING(Service_NVDRV, "(STUBBED) called");
 
     IoctlFlushL2 params{};
@@ -284,7 +283,7 @@ NvResult nvhost_ctrl_gpu::FlushL2(const std::vector<u8>& input, std::vector<u8>&
     return NvResult::Success;
 }
 
-NvResult nvhost_ctrl_gpu::GetGpuTime(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvhost_ctrl_gpu::GetGpuTime(std::span<const u8> input, std::vector<u8>& output) {
     LOG_DEBUG(Service_NVDRV, "called");
 
     IoctlGetGpuTime params{};
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h
index 1e8f254e2f..b9333d9d39 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h
@@ -21,12 +21,12 @@ public:
     explicit nvhost_ctrl_gpu(Core::System& system_, EventInterface& events_interface_);
     ~nvhost_ctrl_gpu() override;
 
-    NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
+    NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
                     std::vector<u8>& output) override;
-    NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
-                    const std::vector<u8>& inline_input, std::vector<u8>& output) override;
-    NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
-                    std::vector<u8>& output, std::vector<u8>& inline_output) override;
+    NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
+                    std::span<const u8> inline_input, std::vector<u8>& output) override;
+    NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output,
+                    std::vector<u8>& inline_output) override;
 
     void OnOpen(DeviceFD fd) override;
     void OnClose(DeviceFD fd) override;
@@ -151,21 +151,21 @@ private:
     };
     static_assert(sizeof(IoctlGetGpuTime) == 0x10, "IoctlGetGpuTime is incorrect size");
 
-    NvResult GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output,
+    NvResult GetCharacteristics(std::span<const u8> input, std::vector<u8>& output);
+    NvResult GetCharacteristics(std::span<const u8> input, std::vector<u8>& output,
                                 std::vector<u8>& inline_output);
 
-    NvResult GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output,
+    NvResult GetTPCMasks(std::span<const u8> input, std::vector<u8>& output);
+    NvResult GetTPCMasks(std::span<const u8> input, std::vector<u8>& output,
                          std::vector<u8>& inline_output);
 
-    NvResult GetActiveSlotMask(const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult ZBCSetTable(const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult ZBCQueryTable(const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult FlushL2(const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult GetGpuTime(const std::vector<u8>& input, std::vector<u8>& output);
+    NvResult GetActiveSlotMask(std::span<const u8> input, std::vector<u8>& output);
+    NvResult ZCullGetCtxSize(std::span<const u8> input, std::vector<u8>& output);
+    NvResult ZCullGetInfo(std::span<const u8> input, std::vector<u8>& output);
+    NvResult ZBCSetTable(std::span<const u8> input, std::vector<u8>& output);
+    NvResult ZBCQueryTable(std::span<const u8> input, std::vector<u8>& output);
+    NvResult FlushL2(std::span<const u8> input, std::vector<u8>& output);
+    NvResult GetGpuTime(std::span<const u8> input, std::vector<u8>& output);
 
     EventInterface& events_interface;
 
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
index e123564c61..d2308fffc9 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
@@ -46,7 +46,7 @@ nvhost_gpu::~nvhost_gpu() {
     syncpoint_manager.FreeSyncpoint(channel_syncpoint);
 }
 
-NvResult nvhost_gpu::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
+NvResult nvhost_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
                             std::vector<u8>& output) {
     switch (command.group) {
     case 0x0:
@@ -98,8 +98,8 @@ NvResult nvhost_gpu::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& i
     return NvResult::NotImplemented;
 };
 
-NvResult nvhost_gpu::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
-                            const std::vector<u8>& inline_input, std::vector<u8>& output) {
+NvResult nvhost_gpu::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
+                            std::span<const u8> inline_input, std::vector<u8>& output) {
     switch (command.group) {
     case 'H':
         switch (command.cmd) {
@@ -112,7 +112,7 @@ NvResult nvhost_gpu::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& i
     return NvResult::NotImplemented;
 }
 
-NvResult nvhost_gpu::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
+NvResult nvhost_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input,
                             std::vector<u8>& output, std::vector<u8>& inline_output) {
     UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
     return NvResult::NotImplemented;
@@ -121,7 +121,7 @@ NvResult nvhost_gpu::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& i
 void nvhost_gpu::OnOpen(DeviceFD fd) {}
 void nvhost_gpu::OnClose(DeviceFD fd) {}
 
-NvResult nvhost_gpu::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvhost_gpu::SetNVMAPfd(std::span<const u8> input, std::vector<u8>& output) {
     IoctlSetNvmapFD params{};
     std::memcpy(&params, input.data(), input.size());
     LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd);
@@ -130,7 +130,7 @@ NvResult nvhost_gpu::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& o
     return NvResult::Success;
 }
 
-NvResult nvhost_gpu::SetClientData(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvhost_gpu::SetClientData(std::span<const u8> input, std::vector<u8>& output) {
     LOG_DEBUG(Service_NVDRV, "called");
 
     IoctlClientData params{};
@@ -139,7 +139,7 @@ NvResult nvhost_gpu::SetClientData(const std::vector<u8>& input, std::vector<u8>
     return NvResult::Success;
 }
 
-NvResult nvhost_gpu::GetClientData(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvhost_gpu::GetClientData(std::span<const u8> input, std::vector<u8>& output) {
     LOG_DEBUG(Service_NVDRV, "called");
 
     IoctlClientData params{};
@@ -149,7 +149,7 @@ NvResult nvhost_gpu::GetClientData(const std::vector<u8>& input, std::vector<u8>
     return NvResult::Success;
 }
 
-NvResult nvhost_gpu::ZCullBind(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvhost_gpu::ZCullBind(std::span<const u8> input, std::vector<u8>& output) {
     std::memcpy(&zcull_params, input.data(), input.size());
     LOG_DEBUG(Service_NVDRV, "called, gpu_va={:X}, mode={:X}", zcull_params.gpu_va,
               zcull_params.mode);
@@ -158,7 +158,7 @@ NvResult nvhost_gpu::ZCullBind(const std::vector<u8>& input, std::vector<u8>& ou
     return NvResult::Success;
 }
 
-NvResult nvhost_gpu::SetErrorNotifier(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvhost_gpu::SetErrorNotifier(std::span<const u8> input, std::vector<u8>& output) {
     IoctlSetErrorNotifier params{};
     std::memcpy(&params, input.data(), input.size());
     LOG_WARNING(Service_NVDRV, "(STUBBED) called, offset={:X}, size={:X}, mem={:X}", params.offset,
@@ -168,14 +168,14 @@ NvResult nvhost_gpu::SetErrorNotifier(const std::vector<u8>& input, std::vector<
     return NvResult::Success;
 }
 
-NvResult nvhost_gpu::SetChannelPriority(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvhost_gpu::SetChannelPriority(std::span<const u8> input, std::vector<u8>& output) {
     std::memcpy(&channel_priority, input.data(), input.size());
     LOG_DEBUG(Service_NVDRV, "(STUBBED) called, priority={:X}", channel_priority);
 
     return NvResult::Success;
 }
 
-NvResult nvhost_gpu::AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvhost_gpu::AllocGPFIFOEx2(std::span<const u8> input, std::vector<u8>& output) {
     IoctlAllocGpfifoEx2 params{};
     std::memcpy(&params, input.data(), input.size());
     LOG_WARNING(Service_NVDRV,
@@ -197,7 +197,7 @@ NvResult nvhost_gpu::AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8
     return NvResult::Success;
 }
 
-NvResult nvhost_gpu::AllocateObjectContext(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvhost_gpu::AllocateObjectContext(std::span<const u8> input, std::vector<u8>& output) {
     IoctlAllocObjCtx params{};
     std::memcpy(&params, input.data(), input.size());
     LOG_WARNING(Service_NVDRV, "(STUBBED) called, class_num={:X}, flags={:X}", params.class_num,
@@ -293,7 +293,7 @@ NvResult nvhost_gpu::SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::vector<u8>
     return NvResult::Success;
 }
 
-NvResult nvhost_gpu::SubmitGPFIFOBase(const std::vector<u8>& input, std::vector<u8>& output,
+NvResult nvhost_gpu::SubmitGPFIFOBase(std::span<const u8> input, std::vector<u8>& output,
                                       bool kickoff) {
     if (input.size() < sizeof(IoctlSubmitGpfifo)) {
         UNIMPLEMENTED();
@@ -314,8 +314,7 @@ NvResult nvhost_gpu::SubmitGPFIFOBase(const std::vector<u8>& input, std::vector<
     return SubmitGPFIFOImpl(params, output, std::move(entries));
 }
 
-NvResult nvhost_gpu::SubmitGPFIFOBase(const std::vector<u8>& input,
-                                      const std::vector<u8>& input_inline,
+NvResult nvhost_gpu::SubmitGPFIFOBase(std::span<const u8> input, std::span<const u8> input_inline,
                                       std::vector<u8>& output) {
     if (input.size() < sizeof(IoctlSubmitGpfifo)) {
         UNIMPLEMENTED();
@@ -328,7 +327,7 @@ NvResult nvhost_gpu::SubmitGPFIFOBase(const std::vector<u8>& input,
     return SubmitGPFIFOImpl(params, output, std::move(entries));
 }
 
-NvResult nvhost_gpu::GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvhost_gpu::GetWaitbase(std::span<const u8> input, std::vector<u8>& output) {
     IoctlGetWaitbase params{};
     std::memcpy(&params, input.data(), sizeof(IoctlGetWaitbase));
     LOG_INFO(Service_NVDRV, "called, unknown=0x{:X}", params.unknown);
@@ -338,7 +337,7 @@ NvResult nvhost_gpu::GetWaitbase(const std::vector<u8>& input, std::vector<u8>&
     return NvResult::Success;
 }
 
-NvResult nvhost_gpu::ChannelSetTimeout(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvhost_gpu::ChannelSetTimeout(std::span<const u8> input, std::vector<u8>& output) {
     IoctlChannelSetTimeout params{};
     std::memcpy(&params, input.data(), sizeof(IoctlChannelSetTimeout));
     LOG_INFO(Service_NVDRV, "called, timeout=0x{:X}", params.timeout);
@@ -346,7 +345,7 @@ NvResult nvhost_gpu::ChannelSetTimeout(const std::vector<u8>& input, std::vector
     return NvResult::Success;
 }
 
-NvResult nvhost_gpu::ChannelSetTimeslice(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvhost_gpu::ChannelSetTimeslice(std::span<const u8> input, std::vector<u8>& output) {
     IoctlSetTimeslice params{};
     std::memcpy(&params, input.data(), sizeof(IoctlSetTimeslice));
     LOG_INFO(Service_NVDRV, "called, timeslice=0x{:X}", params.timeslice);
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
index 1e4ecd55b3..3ca58202d3 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
@@ -40,12 +40,12 @@ public:
                         NvCore::Container& core);
     ~nvhost_gpu() override;
 
-    NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
+    NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
                     std::vector<u8>& output) override;
-    NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
-                    const std::vector<u8>& inline_input, std::vector<u8>& output) override;
-    NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
-                    std::vector<u8>& output, std::vector<u8>& inline_output) override;
+    NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
+                    std::span<const u8> inline_input, std::vector<u8>& output) override;
+    NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output,
+                    std::vector<u8>& inline_output) override;
 
     void OnOpen(DeviceFD fd) override;
     void OnClose(DeviceFD fd) override;
@@ -186,23 +186,23 @@ private:
     u32_le channel_priority{};
     u32_le channel_timeslice{};
 
-    NvResult SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult SetClientData(const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult GetClientData(const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult ZCullBind(const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult SetErrorNotifier(const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult SetChannelPriority(const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult AllocateObjectContext(const std::vector<u8>& input, std::vector<u8>& output);
+    NvResult SetNVMAPfd(std::span<const u8> input, std::vector<u8>& output);
+    NvResult SetClientData(std::span<const u8> input, std::vector<u8>& output);
+    NvResult GetClientData(std::span<const u8> input, std::vector<u8>& output);
+    NvResult ZCullBind(std::span<const u8> input, std::vector<u8>& output);
+    NvResult SetErrorNotifier(std::span<const u8> input, std::vector<u8>& output);
+    NvResult SetChannelPriority(std::span<const u8> input, std::vector<u8>& output);
+    NvResult AllocGPFIFOEx2(std::span<const u8> input, std::vector<u8>& output);
+    NvResult AllocateObjectContext(std::span<const u8> input, std::vector<u8>& output);
     NvResult SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::vector<u8>& output,
                               Tegra::CommandList&& entries);
-    NvResult SubmitGPFIFOBase(const std::vector<u8>& input, std::vector<u8>& output,
+    NvResult SubmitGPFIFOBase(std::span<const u8> input, std::vector<u8>& output,
                               bool kickoff = false);
-    NvResult SubmitGPFIFOBase(const std::vector<u8>& input, const std::vector<u8>& input_inline,
+    NvResult SubmitGPFIFOBase(std::span<const u8> input, std::span<const u8> input_inline,
                               std::vector<u8>& output);
-    NvResult GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult ChannelSetTimeout(const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult ChannelSetTimeslice(const std::vector<u8>& input, std::vector<u8>& output);
+    NvResult GetWaitbase(std::span<const u8> input, std::vector<u8>& output);
+    NvResult ChannelSetTimeout(std::span<const u8> input, std::vector<u8>& output);
+    NvResult ChannelSetTimeslice(std::span<const u8> input, std::vector<u8>& output);
 
     EventInterface& events_interface;
     NvCore::Container& core;
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
index 1703f9cc37..0c7aee1b83 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
@@ -15,7 +15,7 @@ nvhost_nvdec::nvhost_nvdec(Core::System& system_, NvCore::Container& core_)
     : nvhost_nvdec_common{system_, core_, NvCore::ChannelType::NvDec} {}
 nvhost_nvdec::~nvhost_nvdec() = default;
 
-NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
+NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
                               std::vector<u8>& output) {
     switch (command.group) {
     case 0x0:
@@ -55,13 +55,13 @@ NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>&
     return NvResult::NotImplemented;
 }
 
-NvResult nvhost_nvdec::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
-                              const std::vector<u8>& inline_input, std::vector<u8>& output) {
+NvResult nvhost_nvdec::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
+                              std::span<const u8> inline_input, std::vector<u8>& output) {
     UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
     return NvResult::NotImplemented;
 }
 
-NvResult nvhost_nvdec::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
+NvResult nvhost_nvdec::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input,
                               std::vector<u8>& output, std::vector<u8>& inline_output) {
     UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
     return NvResult::NotImplemented;
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h
index c1b4e53e83..0d615bbcbf 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h
@@ -13,12 +13,12 @@ public:
     explicit nvhost_nvdec(Core::System& system_, NvCore::Container& core);
     ~nvhost_nvdec() override;
 
-    NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
+    NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
                     std::vector<u8>& output) override;
-    NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
-                    const std::vector<u8>& inline_input, std::vector<u8>& output) override;
-    NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
-                    std::vector<u8>& output, std::vector<u8>& inline_output) override;
+    NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
+                    std::span<const u8> inline_input, std::vector<u8>& output) override;
+    NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output,
+                    std::vector<u8>& inline_output) override;
 
     void OnOpen(DeviceFD fd) override;
     void OnClose(DeviceFD fd) override;
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp
index 99eede702f..7bcef105b1 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp
@@ -23,7 +23,7 @@ namespace {
 // Copies count amount of type T from the input vector into the dst vector.
 // Returns the number of bytes written into dst.
 template <typename T>
-std::size_t SliceVectors(const std::vector<u8>& input, std::vector<T>& dst, std::size_t count,
+std::size_t SliceVectors(std::span<const u8> input, std::vector<T>& dst, std::size_t count,
                          std::size_t offset) {
     if (dst.empty()) {
         return 0;
@@ -63,7 +63,7 @@ nvhost_nvdec_common::~nvhost_nvdec_common() {
     core.Host1xDeviceFile().syncpts_accumulated.push_back(channel_syncpoint);
 }
 
-NvResult nvhost_nvdec_common::SetNVMAPfd(const std::vector<u8>& input) {
+NvResult nvhost_nvdec_common::SetNVMAPfd(std::span<const u8> input) {
     IoctlSetNvmapFD params{};
     std::memcpy(&params, input.data(), sizeof(IoctlSetNvmapFD));
     LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd);
@@ -72,7 +72,7 @@ NvResult nvhost_nvdec_common::SetNVMAPfd(const std::vector<u8>& input) {
     return NvResult::Success;
 }
 
-NvResult nvhost_nvdec_common::Submit(DeviceFD fd, const std::vector<u8>& input,
+NvResult nvhost_nvdec_common::Submit(DeviceFD fd, std::span<const u8> input,
                                      std::vector<u8>& output) {
     IoctlSubmit params{};
     std::memcpy(&params, input.data(), sizeof(IoctlSubmit));
@@ -121,7 +121,7 @@ NvResult nvhost_nvdec_common::Submit(DeviceFD fd, const std::vector<u8>& input,
     return NvResult::Success;
 }
 
-NvResult nvhost_nvdec_common::GetSyncpoint(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvhost_nvdec_common::GetSyncpoint(std::span<const u8> input, std::vector<u8>& output) {
     IoctlGetSyncpoint params{};
     std::memcpy(&params, input.data(), sizeof(IoctlGetSyncpoint));
     LOG_DEBUG(Service_NVDRV, "called GetSyncpoint, id={}", params.param);
@@ -133,7 +133,7 @@ NvResult nvhost_nvdec_common::GetSyncpoint(const std::vector<u8>& input, std::ve
     return NvResult::Success;
 }
 
-NvResult nvhost_nvdec_common::GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvhost_nvdec_common::GetWaitbase(std::span<const u8> input, std::vector<u8>& output) {
     IoctlGetWaitbase params{};
     LOG_CRITICAL(Service_NVDRV, "called WAITBASE");
     std::memcpy(&params, input.data(), sizeof(IoctlGetWaitbase));
@@ -142,7 +142,7 @@ NvResult nvhost_nvdec_common::GetWaitbase(const std::vector<u8>& input, std::vec
     return NvResult::Success;
 }
 
-NvResult nvhost_nvdec_common::MapBuffer(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvhost_nvdec_common::MapBuffer(std::span<const u8> input, std::vector<u8>& output) {
     IoctlMapBuffer params{};
     std::memcpy(&params, input.data(), sizeof(IoctlMapBuffer));
     std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries);
@@ -159,7 +159,7 @@ NvResult nvhost_nvdec_common::MapBuffer(const std::vector<u8>& input, std::vecto
     return NvResult::Success;
 }
 
-NvResult nvhost_nvdec_common::UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvhost_nvdec_common::UnmapBuffer(std::span<const u8> input, std::vector<u8>& output) {
     IoctlMapBuffer params{};
     std::memcpy(&params, input.data(), sizeof(IoctlMapBuffer));
     std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries);
@@ -173,8 +173,7 @@ NvResult nvhost_nvdec_common::UnmapBuffer(const std::vector<u8>& input, std::vec
     return NvResult::Success;
 }
 
-NvResult nvhost_nvdec_common::SetSubmitTimeout(const std::vector<u8>& input,
-                                               std::vector<u8>& output) {
+NvResult nvhost_nvdec_common::SetSubmitTimeout(std::span<const u8> input, std::vector<u8>& output) {
     std::memcpy(&submit_timeout, input.data(), input.size());
     LOG_WARNING(Service_NVDRV, "(STUBBED) called");
     return NvResult::Success;
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h
index fe76100c86..5af26a26fa 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h
@@ -107,13 +107,13 @@ protected:
     static_assert(sizeof(IoctlMapBuffer) == 0x0C, "IoctlMapBuffer is incorrect size");
 
     /// Ioctl command implementations
-    NvResult SetNVMAPfd(const std::vector<u8>& input);
-    NvResult Submit(DeviceFD fd, const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult GetSyncpoint(const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult MapBuffer(const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult SetSubmitTimeout(const std::vector<u8>& input, std::vector<u8>& output);
+    NvResult SetNVMAPfd(std::span<const u8> input);
+    NvResult Submit(DeviceFD fd, std::span<const u8> input, std::vector<u8>& output);
+    NvResult GetSyncpoint(std::span<const u8> input, std::vector<u8>& output);
+    NvResult GetWaitbase(std::span<const u8> input, std::vector<u8>& output);
+    NvResult MapBuffer(std::span<const u8> input, std::vector<u8>& output);
+    NvResult UnmapBuffer(std::span<const u8> input, std::vector<u8>& output);
+    NvResult SetSubmitTimeout(std::span<const u8> input, std::vector<u8>& output);
 
     Kernel::KEvent* QueryEvent(u32 event_id) override;
 
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp
index bdbc2f9e1f..39f30e7c86 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp
@@ -12,7 +12,7 @@ namespace Service::Nvidia::Devices {
 nvhost_nvjpg::nvhost_nvjpg(Core::System& system_) : nvdevice{system_} {}
 nvhost_nvjpg::~nvhost_nvjpg() = default;
 
-NvResult nvhost_nvjpg::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
+NvResult nvhost_nvjpg::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
                               std::vector<u8>& output) {
     switch (command.group) {
     case 'H':
@@ -31,13 +31,13 @@ NvResult nvhost_nvjpg::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>&
     return NvResult::NotImplemented;
 }
 
-NvResult nvhost_nvjpg::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
-                              const std::vector<u8>& inline_input, std::vector<u8>& output) {
+NvResult nvhost_nvjpg::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
+                              std::span<const u8> inline_input, std::vector<u8>& output) {
     UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
     return NvResult::NotImplemented;
 }
 
-NvResult nvhost_nvjpg::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
+NvResult nvhost_nvjpg::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input,
                               std::vector<u8>& output, std::vector<u8>& inline_output) {
     UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
     return NvResult::NotImplemented;
@@ -46,7 +46,7 @@ NvResult nvhost_nvjpg::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>&
 void nvhost_nvjpg::OnOpen(DeviceFD fd) {}
 void nvhost_nvjpg::OnClose(DeviceFD fd) {}
 
-NvResult nvhost_nvjpg::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvhost_nvjpg::SetNVMAPfd(std::span<const u8> input, std::vector<u8>& output) {
     IoctlSetNvmapFD params{};
     std::memcpy(&params, input.data(), input.size());
     LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd);
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h
index 440e7d371c..41b57e872d 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h
@@ -15,12 +15,12 @@ public:
     explicit nvhost_nvjpg(Core::System& system_);
     ~nvhost_nvjpg() override;
 
-    NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
+    NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
                     std::vector<u8>& output) override;
-    NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
-                    const std::vector<u8>& inline_input, std::vector<u8>& output) override;
-    NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
-                    std::vector<u8>& output, std::vector<u8>& inline_output) override;
+    NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
+                    std::span<const u8> inline_input, std::vector<u8>& output) override;
+    NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output,
+                    std::vector<u8>& inline_output) override;
 
     void OnOpen(DeviceFD fd) override;
     void OnClose(DeviceFD fd) override;
@@ -33,7 +33,7 @@ private:
 
     s32_le nvmap_fd{};
 
-    NvResult SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output);
+    NvResult SetNVMAPfd(std::span<const u8> input, std::vector<u8>& output);
 };
 
 } // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp
index 73f97136e3..b0ea402a72 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp
@@ -15,7 +15,7 @@ nvhost_vic::nvhost_vic(Core::System& system_, NvCore::Container& core_)
 
 nvhost_vic::~nvhost_vic() = default;
 
-NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
+NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
                             std::vector<u8>& output) {
     switch (command.group) {
     case 0x0:
@@ -55,13 +55,13 @@ NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& i
     return NvResult::NotImplemented;
 }
 
-NvResult nvhost_vic::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
-                            const std::vector<u8>& inline_input, std::vector<u8>& output) {
+NvResult nvhost_vic::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
+                            std::span<const u8> inline_input, std::vector<u8>& output) {
     UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
     return NvResult::NotImplemented;
 }
 
-NvResult nvhost_vic::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
+NvResult nvhost_vic::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input,
                             std::vector<u8>& output, std::vector<u8>& inline_output) {
     UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
     return NvResult::NotImplemented;
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.h b/src/core/hle/service/nvdrv/devices/nvhost_vic.h
index f164caafb3..b5e350a83d 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_vic.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.h
@@ -12,12 +12,12 @@ public:
     explicit nvhost_vic(Core::System& system_, NvCore::Container& core);
     ~nvhost_vic();
 
-    NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
+    NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
                     std::vector<u8>& output) override;
-    NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
-                    const std::vector<u8>& inline_input, std::vector<u8>& output) override;
-    NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
-                    std::vector<u8>& output, std::vector<u8>& inline_output) override;
+    NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
+                    std::span<const u8> inline_input, std::vector<u8>& output) override;
+    NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output,
+                    std::vector<u8>& inline_output) override;
 
     void OnOpen(DeviceFD fd) override;
     void OnClose(DeviceFD fd) override;
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp
index fa29db7580..29c1e0f011 100644
--- a/src/core/hle/service/nvdrv/devices/nvmap.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp
@@ -25,7 +25,7 @@ nvmap::nvmap(Core::System& system_, NvCore::Container& container_)
 
 nvmap::~nvmap() = default;
 
-NvResult nvmap::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
+NvResult nvmap::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
                        std::vector<u8>& output) {
     switch (command.group) {
     case 0x1:
@@ -54,13 +54,13 @@ NvResult nvmap::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
     return NvResult::NotImplemented;
 }
 
-NvResult nvmap::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
-                       const std::vector<u8>& inline_input, std::vector<u8>& output) {
+NvResult nvmap::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
+                       std::span<const u8> inline_input, std::vector<u8>& output) {
     UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
     return NvResult::NotImplemented;
 }
 
-NvResult nvmap::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
+NvResult nvmap::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input,
                        std::vector<u8>& output, std::vector<u8>& inline_output) {
     UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
     return NvResult::NotImplemented;
@@ -69,7 +69,7 @@ NvResult nvmap::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
 void nvmap::OnOpen(DeviceFD fd) {}
 void nvmap::OnClose(DeviceFD fd) {}
 
-NvResult nvmap::IocCreate(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvmap::IocCreate(std::span<const u8> input, std::vector<u8>& output) {
     IocCreateParams params;
     std::memcpy(&params, input.data(), sizeof(params));
     LOG_DEBUG(Service_NVDRV, "called, size=0x{:08X}", params.size);
@@ -89,7 +89,7 @@ NvResult nvmap::IocCreate(const std::vector<u8>& input, std::vector<u8>& output)
     return NvResult::Success;
 }
 
-NvResult nvmap::IocAlloc(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvmap::IocAlloc(std::span<const u8> input, std::vector<u8>& output) {
     IocAllocParams params;
     std::memcpy(&params, input.data(), sizeof(params));
     LOG_DEBUG(Service_NVDRV, "called, addr={:X}", params.address);
@@ -137,7 +137,7 @@ NvResult nvmap::IocAlloc(const std::vector<u8>& input, std::vector<u8>& output)
     return result;
 }
 
-NvResult nvmap::IocGetId(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvmap::IocGetId(std::span<const u8> input, std::vector<u8>& output) {
     IocGetIdParams params;
     std::memcpy(&params, input.data(), sizeof(params));
 
@@ -161,7 +161,7 @@ NvResult nvmap::IocGetId(const std::vector<u8>& input, std::vector<u8>& output)
     return NvResult::Success;
 }
 
-NvResult nvmap::IocFromId(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvmap::IocFromId(std::span<const u8> input, std::vector<u8>& output) {
     IocFromIdParams params;
     std::memcpy(&params, input.data(), sizeof(params));
 
@@ -192,7 +192,7 @@ NvResult nvmap::IocFromId(const std::vector<u8>& input, std::vector<u8>& output)
     return NvResult::Success;
 }
 
-NvResult nvmap::IocParam(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvmap::IocParam(std::span<const u8> input, std::vector<u8>& output) {
     enum class ParamTypes { Size = 1, Alignment = 2, Base = 3, Heap = 4, Kind = 5, Compr = 6 };
 
     IocParamParams params;
@@ -241,7 +241,7 @@ NvResult nvmap::IocParam(const std::vector<u8>& input, std::vector<u8>& output)
     return NvResult::Success;
 }
 
-NvResult nvmap::IocFree(const std::vector<u8>& input, std::vector<u8>& output) {
+NvResult nvmap::IocFree(std::span<const u8> input, std::vector<u8>& output) {
     IocFreeParams params;
     std::memcpy(&params, input.data(), sizeof(params));
 
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.h b/src/core/hle/service/nvdrv/devices/nvmap.h
index e9bfd03580..82bd3b118f 100644
--- a/src/core/hle/service/nvdrv/devices/nvmap.h
+++ b/src/core/hle/service/nvdrv/devices/nvmap.h
@@ -26,12 +26,12 @@ public:
     nvmap(const nvmap&) = delete;
     nvmap& operator=(const nvmap&) = delete;
 
-    NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
+    NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
                     std::vector<u8>& output) override;
-    NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
-                    const std::vector<u8>& inline_input, std::vector<u8>& output) override;
-    NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
-                    std::vector<u8>& output, std::vector<u8>& inline_output) override;
+    NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
+                    std::span<const u8> inline_input, std::vector<u8>& output) override;
+    NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output,
+                    std::vector<u8>& inline_output) override;
 
     void OnOpen(DeviceFD fd) override;
     void OnClose(DeviceFD fd) override;
@@ -106,12 +106,12 @@ private:
     };
     static_assert(sizeof(IocGetIdParams) == 8, "IocGetIdParams has wrong size");
 
-    NvResult IocCreate(const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult IocAlloc(const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult IocGetId(const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult IocFromId(const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult IocParam(const std::vector<u8>& input, std::vector<u8>& output);
-    NvResult IocFree(const std::vector<u8>& input, std::vector<u8>& output);
+    NvResult IocCreate(std::span<const u8> input, std::vector<u8>& output);
+    NvResult IocAlloc(std::span<const u8> input, std::vector<u8>& output);
+    NvResult IocGetId(std::span<const u8> input, std::vector<u8>& output);
+    NvResult IocFromId(std::span<const u8> input, std::vector<u8>& output);
+    NvResult IocParam(std::span<const u8> input, std::vector<u8>& output);
+    NvResult IocFree(std::span<const u8> input, std::vector<u8>& output);
 
     NvCore::Container& container;
     NvCore::NvMap& file;
diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp
index 6fc8565c0d..52d27e7553 100644
--- a/src/core/hle/service/nvdrv/nvdrv.cpp
+++ b/src/core/hle/service/nvdrv/nvdrv.cpp
@@ -124,7 +124,7 @@ DeviceFD Module::Open(const std::string& device_name) {
     return fd;
 }
 
-NvResult Module::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
+NvResult Module::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
                         std::vector<u8>& output) {
     if (fd < 0) {
         LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd);
@@ -141,8 +141,8 @@ NvResult Module::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input
     return itr->second->Ioctl1(fd, command, input, output);
 }
 
-NvResult Module::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
-                        const std::vector<u8>& inline_input, std::vector<u8>& output) {
+NvResult Module::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
+                        std::span<const u8> inline_input, std::vector<u8>& output) {
     if (fd < 0) {
         LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd);
         return NvResult::InvalidState;
@@ -158,7 +158,7 @@ NvResult Module::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input
     return itr->second->Ioctl2(fd, command, input, inline_input, output);
 }
 
-NvResult Module::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
+NvResult Module::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input,
                         std::vector<u8>& output, std::vector<u8>& inline_output) {
     if (fd < 0) {
         LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd);
diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h
index f3c81bd882..b09b6e5858 100644
--- a/src/core/hle/service/nvdrv/nvdrv.h
+++ b/src/core/hle/service/nvdrv/nvdrv.h
@@ -7,6 +7,7 @@
 #include <functional>
 #include <list>
 #include <memory>
+#include <span>
 #include <string>
 #include <unordered_map>
 #include <vector>
@@ -79,14 +80,13 @@ public:
     DeviceFD Open(const std::string& device_name);
 
     /// Sends an ioctl command to the specified file descriptor.
-    NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
-                    std::vector<u8>& output);
+    NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output);
 
-    NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
-                    const std::vector<u8>& inline_input, std::vector<u8>& output);
+    NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
+                    std::span<const u8> inline_input, std::vector<u8>& output);
 
-    NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
-                    std::vector<u8>& output, std::vector<u8>& inline_output);
+    NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output,
+                    std::vector<u8>& inline_output);
 
     /// Closes a device file descriptor and returns operation success.
     NvResult Close(DeviceFD fd);
diff --git a/src/core/hle/service/nvflinger/buffer_queue_producer.cpp b/src/core/hle/service/nvflinger/buffer_queue_producer.cpp
index e601b5da1c..bcbe05b0d0 100644
--- a/src/core/hle/service/nvflinger/buffer_queue_producer.cpp
+++ b/src/core/hle/service/nvflinger/buffer_queue_producer.cpp
@@ -815,8 +815,8 @@ Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot,
 
 void BufferQueueProducer::Transact(Kernel::HLERequestContext& ctx, TransactionId code, u32 flags) {
     Status status{Status::NoError};
-    Parcel parcel_in{ctx.ReadBuffer()};
-    Parcel parcel_out{};
+    InputParcel parcel_in{ctx.ReadBuffer()};
+    OutputParcel parcel_out{};
 
     switch (code) {
     case TransactionId::Connect: {
diff --git a/src/core/hle/service/nvflinger/graphic_buffer_producer.cpp b/src/core/hle/service/nvflinger/graphic_buffer_producer.cpp
index 4043c91f19..769e8c0a30 100644
--- a/src/core/hle/service/nvflinger/graphic_buffer_producer.cpp
+++ b/src/core/hle/service/nvflinger/graphic_buffer_producer.cpp
@@ -9,7 +9,7 @@
 
 namespace Service::android {
 
-QueueBufferInput::QueueBufferInput(Parcel& parcel) {
+QueueBufferInput::QueueBufferInput(InputParcel& parcel) {
     parcel.ReadFlattened(*this);
 }
 
diff --git a/src/core/hle/service/nvflinger/graphic_buffer_producer.h b/src/core/hle/service/nvflinger/graphic_buffer_producer.h
index 6ea327bbe7..2969f0fd50 100644
--- a/src/core/hle/service/nvflinger/graphic_buffer_producer.h
+++ b/src/core/hle/service/nvflinger/graphic_buffer_producer.h
@@ -14,11 +14,11 @@
 
 namespace Service::android {
 
-class Parcel;
+class InputParcel;
 
 #pragma pack(push, 1)
 struct QueueBufferInput final {
-    explicit QueueBufferInput(Parcel& parcel);
+    explicit QueueBufferInput(InputParcel& parcel);
 
     void Deflate(s64* timestamp_, bool* is_auto_timestamp_, Common::Rectangle<s32>* crop_,
                  NativeWindowScalingMode* scaling_mode_, NativeWindowTransform* transform_,
diff --git a/src/core/hle/service/nvflinger/parcel.h b/src/core/hle/service/nvflinger/parcel.h
index f3fa2587df..d1b6201e0c 100644
--- a/src/core/hle/service/nvflinger/parcel.h
+++ b/src/core/hle/service/nvflinger/parcel.h
@@ -4,6 +4,7 @@
 #pragma once
 
 #include <memory>
+#include <span>
 #include <vector>
 
 #include "common/alignment.h"
@@ -12,18 +13,17 @@
 
 namespace Service::android {
 
-class Parcel final {
+struct ParcelHeader {
+    u32 data_size;
+    u32 data_offset;
+    u32 objects_size;
+    u32 objects_offset;
+};
+static_assert(sizeof(ParcelHeader) == 16, "ParcelHeader has wrong size");
+
+class InputParcel final {
 public:
-    static constexpr std::size_t DefaultBufferSize = 0x40;
-
-    Parcel() : buffer(DefaultBufferSize) {}
-
-    template <typename T>
-    explicit Parcel(const T& out_data) : buffer(DefaultBufferSize) {
-        Write(out_data);
-    }
-
-    explicit Parcel(std::vector<u8> in_data) : buffer(std::move(in_data)) {
+    explicit InputParcel(std::span<const u8> in_data) : read_buffer(std::move(in_data)) {
         DeserializeHeader();
         [[maybe_unused]] const std::u16string token = ReadInterfaceToken();
     }
@@ -31,9 +31,9 @@ public:
     template <typename T>
     void Read(T& val) {
         static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable.");
-        ASSERT(read_index + sizeof(T) <= buffer.size());
+        ASSERT(read_index + sizeof(T) <= read_buffer.size());
 
-        std::memcpy(&val, buffer.data() + read_index, sizeof(T));
+        std::memcpy(&val, read_buffer.data() + read_index, sizeof(T));
         read_index += sizeof(T);
         read_index = Common::AlignUp(read_index, 4);
     }
@@ -62,10 +62,10 @@ public:
     template <typename T>
     T ReadUnaligned() {
         static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable.");
-        ASSERT(read_index + sizeof(T) <= buffer.size());
+        ASSERT(read_index + sizeof(T) <= read_buffer.size());
 
         T val;
-        std::memcpy(&val, buffer.data() + read_index, sizeof(T));
+        std::memcpy(&val, read_buffer.data() + read_index, sizeof(T));
         read_index += sizeof(T);
         return val;
     }
@@ -101,6 +101,31 @@ public:
         return token;
     }
 
+    void DeserializeHeader() {
+        ASSERT(read_buffer.size() > sizeof(ParcelHeader));
+
+        ParcelHeader header{};
+        std::memcpy(&header, read_buffer.data(), sizeof(ParcelHeader));
+
+        read_index = header.data_offset;
+    }
+
+private:
+    std::span<const u8> read_buffer;
+    std::size_t read_index = 0;
+};
+
+class OutputParcel final {
+public:
+    static constexpr std::size_t DefaultBufferSize = 0x40;
+
+    OutputParcel() : buffer(DefaultBufferSize) {}
+
+    template <typename T>
+    explicit OutputParcel(const T& out_data) : buffer(DefaultBufferSize) {
+        Write(out_data);
+    }
+
     template <typename T>
     void Write(const T& val) {
         static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable.");
@@ -133,40 +158,20 @@ public:
         WriteObject(ptr.get());
     }
 
-    void DeserializeHeader() {
-        ASSERT(buffer.size() > sizeof(Header));
-
-        Header header{};
-        std::memcpy(&header, buffer.data(), sizeof(Header));
-
-        read_index = header.data_offset;
-    }
-
     std::vector<u8> Serialize() const {
-        ASSERT(read_index == 0);
-
-        Header header{};
-        header.data_size = static_cast<u32>(write_index - sizeof(Header));
-        header.data_offset = sizeof(Header);
+        ParcelHeader header{};
+        header.data_size = static_cast<u32>(write_index - sizeof(ParcelHeader));
+        header.data_offset = sizeof(ParcelHeader);
         header.objects_size = 4;
-        header.objects_offset = static_cast<u32>(sizeof(Header) + header.data_size);
-        std::memcpy(buffer.data(), &header, sizeof(Header));
+        header.objects_offset = static_cast<u32>(sizeof(ParcelHeader) + header.data_size);
+        std::memcpy(buffer.data(), &header, sizeof(ParcelHeader));
 
         return buffer;
     }
 
 private:
-    struct Header {
-        u32 data_size;
-        u32 data_offset;
-        u32 objects_size;
-        u32 objects_offset;
-    };
-    static_assert(sizeof(Header) == 16, "ParcelHeader has wrong size");
-
     mutable std::vector<u8> buffer;
-    std::size_t read_index = 0;
-    std::size_t write_index = sizeof(Header);
+    std::size_t write_index = sizeof(ParcelHeader);
 };
 
 } // namespace Service::android
diff --git a/src/core/hle/service/prepo/prepo.cpp b/src/core/hle/service/prepo/prepo.cpp
index 78f897d3e6..01040b32a8 100644
--- a/src/core/hle/service/prepo/prepo.cpp
+++ b/src/core/hle/service/prepo/prepo.cpp
@@ -63,7 +63,7 @@ private:
                 return ctx.ReadBuffer(1);
             }
 
-            return std::vector<u8>{};
+            return std::span<const u8>{};
         }();
 
         LOG_DEBUG(Service_PREPO,
@@ -90,7 +90,7 @@ private:
                 return ctx.ReadBuffer(1);
             }
 
-            return std::vector<u8>{};
+            return std::span<const u8>{};
         }();
 
         LOG_DEBUG(Service_PREPO,
@@ -142,7 +142,7 @@ private:
                 return ctx.ReadBuffer(1);
             }
 
-            return std::vector<u8>{};
+            return std::span<const u8>{};
         }();
 
         LOG_DEBUG(Service_PREPO, "called, title_id={:016X}, data1_size={:016X}, data2_size={:016X}",
@@ -166,7 +166,7 @@ private:
                 return ctx.ReadBuffer(1);
             }
 
-            return std::vector<u8>{};
+            return std::span<const u8>{};
         }();
 
         LOG_DEBUG(Service_PREPO,
diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp
index 9e94a462f7..bdb4992688 100644
--- a/src/core/hle/service/sockets/bsd.cpp
+++ b/src/core/hle/service/sockets/bsd.cpp
@@ -208,7 +208,6 @@ void BSD::Bind(Kernel::HLERequestContext& ctx) {
     const s32 fd = rp.Pop<s32>();
 
     LOG_DEBUG(Service, "called. fd={} addrlen={}", fd, ctx.GetReadBufferSize());
-
     BuildErrnoResponse(ctx, BindImpl(fd, ctx.ReadBuffer()));
 }
 
@@ -312,7 +311,7 @@ void BSD::SetSockOpt(Kernel::HLERequestContext& ctx) {
     const u32 level = rp.Pop<u32>();
     const OptName optname = static_cast<OptName>(rp.Pop<u32>());
 
-    const std::vector<u8> buffer = ctx.ReadBuffer();
+    const auto buffer = ctx.ReadBuffer();
     const u8* optval = buffer.empty() ? nullptr : buffer.data();
     size_t optlen = buffer.size();
 
@@ -489,7 +488,7 @@ std::pair<s32, Errno> BSD::SocketImpl(Domain domain, Type type, Protocol protoco
     return {fd, Errno::SUCCESS};
 }
 
-std::pair<s32, Errno> BSD::PollImpl(std::vector<u8>& write_buffer, std::vector<u8> read_buffer,
+std::pair<s32, Errno> BSD::PollImpl(std::vector<u8>& write_buffer, std::span<const u8> read_buffer,
                                     s32 nfds, s32 timeout) {
     if (write_buffer.size() < nfds * sizeof(PollFD)) {
         return {-1, Errno::INVAL};
@@ -584,7 +583,7 @@ std::pair<s32, Errno> BSD::AcceptImpl(s32 fd, std::vector<u8>& write_buffer) {
     return {new_fd, Errno::SUCCESS};
 }
 
-Errno BSD::BindImpl(s32 fd, const std::vector<u8>& addr) {
+Errno BSD::BindImpl(s32 fd, std::span<const u8> addr) {
     if (!IsFileDescriptorValid(fd)) {
         return Errno::BADF;
     }
@@ -595,7 +594,7 @@ Errno BSD::BindImpl(s32 fd, const std::vector<u8>& addr) {
     return Translate(file_descriptors[fd]->socket->Bind(Translate(addr_in)));
 }
 
-Errno BSD::ConnectImpl(s32 fd, const std::vector<u8>& addr) {
+Errno BSD::ConnectImpl(s32 fd, std::span<const u8> addr) {
     if (!IsFileDescriptorValid(fd)) {
         return Errno::BADF;
     }
@@ -800,15 +799,15 @@ std::pair<s32, Errno> BSD::RecvFromImpl(s32 fd, u32 flags, std::vector<u8>& mess
     return {ret, bsd_errno};
 }
 
-std::pair<s32, Errno> BSD::SendImpl(s32 fd, u32 flags, const std::vector<u8>& message) {
+std::pair<s32, Errno> BSD::SendImpl(s32 fd, u32 flags, std::span<const u8> message) {
     if (!IsFileDescriptorValid(fd)) {
         return {-1, Errno::BADF};
     }
     return Translate(file_descriptors[fd]->socket->Send(message, flags));
 }
 
-std::pair<s32, Errno> BSD::SendToImpl(s32 fd, u32 flags, const std::vector<u8>& message,
-                                      const std::vector<u8>& addr) {
+std::pair<s32, Errno> BSD::SendToImpl(s32 fd, u32 flags, std::span<const u8> message,
+                                      std::span<const u8> addr) {
     if (!IsFileDescriptorValid(fd)) {
         return {-1, Errno::BADF};
     }
diff --git a/src/core/hle/service/sockets/bsd.h b/src/core/hle/service/sockets/bsd.h
index 81e855e0fa..56bb3f8b1f 100644
--- a/src/core/hle/service/sockets/bsd.h
+++ b/src/core/hle/service/sockets/bsd.h
@@ -4,6 +4,7 @@
 #pragma once
 
 #include <memory>
+#include <span>
 #include <vector>
 
 #include "common/common_types.h"
@@ -44,7 +45,7 @@ private:
 
         s32 nfds;
         s32 timeout;
-        std::vector<u8> read_buffer;
+        std::span<const u8> read_buffer;
         std::vector<u8> write_buffer;
         s32 ret{};
         Errno bsd_errno{};
@@ -65,7 +66,7 @@ private:
         void Response(Kernel::HLERequestContext& ctx);
 
         s32 fd;
-        std::vector<u8> addr;
+        std::span<const u8> addr;
         Errno bsd_errno{};
     };
 
@@ -98,7 +99,7 @@ private:
 
         s32 fd;
         u32 flags;
-        std::vector<u8> message;
+        std::span<const u8> message;
         s32 ret{};
         Errno bsd_errno{};
     };
@@ -109,8 +110,8 @@ private:
 
         s32 fd;
         u32 flags;
-        std::vector<u8> message;
-        std::vector<u8> addr;
+        std::span<const u8> message;
+        std::span<const u8> addr;
         s32 ret{};
         Errno bsd_errno{};
     };
@@ -143,11 +144,11 @@ private:
     void ExecuteWork(Kernel::HLERequestContext& ctx, Work work);
 
     std::pair<s32, Errno> SocketImpl(Domain domain, Type type, Protocol protocol);
-    std::pair<s32, Errno> PollImpl(std::vector<u8>& write_buffer, std::vector<u8> read_buffer,
+    std::pair<s32, Errno> PollImpl(std::vector<u8>& write_buffer, std::span<const u8> read_buffer,
                                    s32 nfds, s32 timeout);
     std::pair<s32, Errno> AcceptImpl(s32 fd, std::vector<u8>& write_buffer);
-    Errno BindImpl(s32 fd, const std::vector<u8>& addr);
-    Errno ConnectImpl(s32 fd, const std::vector<u8>& addr);
+    Errno BindImpl(s32 fd, std::span<const u8> addr);
+    Errno ConnectImpl(s32 fd, std::span<const u8> addr);
     Errno GetPeerNameImpl(s32 fd, std::vector<u8>& write_buffer);
     Errno GetSockNameImpl(s32 fd, std::vector<u8>& write_buffer);
     Errno ListenImpl(s32 fd, s32 backlog);
@@ -157,9 +158,9 @@ private:
     std::pair<s32, Errno> RecvImpl(s32 fd, u32 flags, std::vector<u8>& message);
     std::pair<s32, Errno> RecvFromImpl(s32 fd, u32 flags, std::vector<u8>& message,
                                        std::vector<u8>& addr);
-    std::pair<s32, Errno> SendImpl(s32 fd, u32 flags, const std::vector<u8>& message);
-    std::pair<s32, Errno> SendToImpl(s32 fd, u32 flags, const std::vector<u8>& message,
-                                     const std::vector<u8>& addr);
+    std::pair<s32, Errno> SendImpl(s32 fd, u32 flags, std::span<const u8> message);
+    std::pair<s32, Errno> SendToImpl(s32 fd, u32 flags, std::span<const u8> message,
+                                     std::span<const u8> addr);
     Errno CloseImpl(s32 fd);
 
     s32 FindFreeFileDescriptorHandle() noexcept;
diff --git a/src/core/hle/service/sockets/sfdnsres.cpp b/src/core/hle/service/sockets/sfdnsres.cpp
index 097c37d7ae..e96eda7f35 100644
--- a/src/core/hle/service/sockets/sfdnsres.cpp
+++ b/src/core/hle/service/sockets/sfdnsres.cpp
@@ -243,4 +243,4 @@ void SFDNSRES::GetAddrInfoRequestWithOptions(Kernel::HLERequestContext& ctx) {
     rb.Push(0);
 }
 
-} // namespace Service::Sockets
\ No newline at end of file
+} // namespace Service::Sockets
diff --git a/src/core/hle/service/ssl/ssl.cpp b/src/core/hle/service/ssl/ssl.cpp
index 3735e0452d..dcf47083f0 100644
--- a/src/core/hle/service/ssl/ssl.cpp
+++ b/src/core/hle/service/ssl/ssl.cpp
@@ -101,7 +101,7 @@ private:
     void ImportServerPki(Kernel::HLERequestContext& ctx) {
         IPC::RequestParser rp{ctx};
         const auto certificate_format = rp.PopEnum<CertificateFormat>();
-        const auto pkcs_12_certificates = ctx.ReadBuffer(0);
+        [[maybe_unused]] const auto pkcs_12_certificates = ctx.ReadBuffer(0);
 
         constexpr u64 server_id = 0;
 
@@ -113,13 +113,13 @@ private:
     }
 
     void ImportClientPki(Kernel::HLERequestContext& ctx) {
-        const auto pkcs_12_certificate = ctx.ReadBuffer(0);
-        const auto ascii_password = [&ctx] {
+        [[maybe_unused]] const auto pkcs_12_certificate = ctx.ReadBuffer(0);
+        [[maybe_unused]] const auto ascii_password = [&ctx] {
             if (ctx.CanReadBuffer(1)) {
                 return ctx.ReadBuffer(1);
             }
 
-            return std::vector<u8>{};
+            return std::span<const u8>{};
         }();
 
         constexpr u64 client_id = 0;
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index bb283e74e3..2fb6311838 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -603,7 +603,7 @@ private:
             return;
         }
 
-        const auto parcel = android::Parcel{NativeWindow{*buffer_queue_id}};
+        const auto parcel = android::OutputParcel{NativeWindow{*buffer_queue_id}};
         const auto buffer_size = ctx.WriteBuffer(parcel.Serialize());
 
         IPC::ResponseBuilder rb{ctx, 4};
@@ -649,7 +649,7 @@ private:
             return;
         }
 
-        const auto parcel = android::Parcel{NativeWindow{*buffer_queue_id}};
+        const auto parcel = android::OutputParcel{NativeWindow{*buffer_queue_id}};
         const auto buffer_size = ctx.WriteBuffer(parcel.Serialize());
 
         IPC::ResponseBuilder rb{ctx, 6};
diff --git a/src/core/internal_network/network.cpp b/src/core/internal_network/network.cpp
index 282ea1ff9d..7494fb62db 100644
--- a/src/core/internal_network/network.cpp
+++ b/src/core/internal_network/network.cpp
@@ -550,7 +550,7 @@ std::pair<s32, Errno> Socket::RecvFrom(int flags, std::vector<u8>& message, Sock
     return {-1, GetAndLogLastError()};
 }
 
-std::pair<s32, Errno> Socket::Send(const std::vector<u8>& message, int flags) {
+std::pair<s32, Errno> Socket::Send(std::span<const u8> message, int flags) {
     ASSERT(message.size() < static_cast<size_t>(std::numeric_limits<int>::max()));
     ASSERT(flags == 0);
 
@@ -563,7 +563,7 @@ std::pair<s32, Errno> Socket::Send(const std::vector<u8>& message, int flags) {
     return {-1, GetAndLogLastError()};
 }
 
-std::pair<s32, Errno> Socket::SendTo(u32 flags, const std::vector<u8>& message,
+std::pair<s32, Errno> Socket::SendTo(u32 flags, std::span<const u8> message,
                                      const SockAddrIn* addr) {
     ASSERT(flags == 0);
 
diff --git a/src/core/internal_network/socket_proxy.cpp b/src/core/internal_network/socket_proxy.cpp
index 1e1c42ceac..7a77171c29 100644
--- a/src/core/internal_network/socket_proxy.cpp
+++ b/src/core/internal_network/socket_proxy.cpp
@@ -182,7 +182,7 @@ std::pair<s32, Errno> ProxySocket::ReceivePacket(int flags, std::vector<u8>& mes
     return {static_cast<u32>(read_bytes), Errno::SUCCESS};
 }
 
-std::pair<s32, Errno> ProxySocket::Send(const std::vector<u8>& message, int flags) {
+std::pair<s32, Errno> ProxySocket::Send(std::span<const u8> message, int flags) {
     LOG_WARNING(Network, "(STUBBED) called");
     ASSERT(message.size() < static_cast<size_t>(std::numeric_limits<int>::max()));
     ASSERT(flags == 0);
@@ -200,7 +200,7 @@ void ProxySocket::SendPacket(ProxyPacket& packet) {
     }
 }
 
-std::pair<s32, Errno> ProxySocket::SendTo(u32 flags, const std::vector<u8>& message,
+std::pair<s32, Errno> ProxySocket::SendTo(u32 flags, std::span<const u8> message,
                                           const SockAddrIn* addr) {
     ASSERT(flags == 0);
 
diff --git a/src/core/internal_network/socket_proxy.h b/src/core/internal_network/socket_proxy.h
index f12b5f5672..9421492bc0 100644
--- a/src/core/internal_network/socket_proxy.h
+++ b/src/core/internal_network/socket_proxy.h
@@ -4,6 +4,7 @@
 #pragma once
 
 #include <mutex>
+#include <span>
 #include <vector>
 #include <queue>
 
@@ -48,11 +49,11 @@ public:
     std::pair<s32, Errno> ReceivePacket(int flags, std::vector<u8>& message, SockAddrIn* addr,
                                         std::size_t max_length);
 
-    std::pair<s32, Errno> Send(const std::vector<u8>& message, int flags) override;
+    std::pair<s32, Errno> Send(std::span<const u8> message, int flags) override;
 
     void SendPacket(ProxyPacket& packet);
 
-    std::pair<s32, Errno> SendTo(u32 flags, const std::vector<u8>& message,
+    std::pair<s32, Errno> SendTo(u32 flags, std::span<const u8> message,
                                  const SockAddrIn* addr) override;
 
     Errno SetLinger(bool enable, u32 linger) override;
diff --git a/src/core/internal_network/sockets.h b/src/core/internal_network/sockets.h
index 2e328c645a..4c74892584 100644
--- a/src/core/internal_network/sockets.h
+++ b/src/core/internal_network/sockets.h
@@ -5,6 +5,7 @@
 
 #include <map>
 #include <memory>
+#include <span>
 #include <utility>
 
 #if defined(_WIN32)
@@ -66,9 +67,9 @@ public:
     virtual std::pair<s32, Errno> RecvFrom(int flags, std::vector<u8>& message,
                                            SockAddrIn* addr) = 0;
 
-    virtual std::pair<s32, Errno> Send(const std::vector<u8>& message, int flags) = 0;
+    virtual std::pair<s32, Errno> Send(std::span<const u8> message, int flags) = 0;
 
-    virtual std::pair<s32, Errno> SendTo(u32 flags, const std::vector<u8>& message,
+    virtual std::pair<s32, Errno> SendTo(u32 flags, std::span<const u8> message,
                                          const SockAddrIn* addr) = 0;
 
     virtual Errno SetLinger(bool enable, u32 linger) = 0;
@@ -138,9 +139,9 @@ public:
 
     std::pair<s32, Errno> RecvFrom(int flags, std::vector<u8>& message, SockAddrIn* addr) override;
 
-    std::pair<s32, Errno> Send(const std::vector<u8>& message, int flags) override;
+    std::pair<s32, Errno> Send(std::span<const u8> message, int flags) override;
 
-    std::pair<s32, Errno> SendTo(u32 flags, const std::vector<u8>& message,
+    std::pair<s32, Errno> SendTo(u32 flags, std::span<const u8> message,
                                  const SockAddrIn* addr) override;
 
     Errno SetLinger(bool enable, u32 linger) override;
diff --git a/src/core/reporter.cpp b/src/core/reporter.cpp
index 77821e047d..59dfb87673 100644
--- a/src/core/reporter.cpp
+++ b/src/core/reporter.cpp
@@ -312,7 +312,7 @@ void Reporter::SaveUnimplementedAppletReport(
 }
 
 void Reporter::SavePlayReport(PlayReportType type, u64 title_id,
-                              const std::vector<std::vector<u8>>& data,
+                              const std::vector<std::span<const u8>>& data,
                               std::optional<u64> process_id, std::optional<u128> user_id) const {
     if (!IsReportingEnabled()) {
         return;
diff --git a/src/core/reporter.h b/src/core/reporter.h
index 9fdb9d6c1b..bb11f8e7c9 100644
--- a/src/core/reporter.h
+++ b/src/core/reporter.h
@@ -5,6 +5,7 @@
 
 #include <array>
 #include <optional>
+#include <span>
 #include <string>
 #include <vector>
 #include "common/common_types.h"
@@ -56,7 +57,8 @@ public:
         System,
     };
 
-    void SavePlayReport(PlayReportType type, u64 title_id, const std::vector<std::vector<u8>>& data,
+    void SavePlayReport(PlayReportType type, u64 title_id,
+                        const std::vector<std::span<const u8>>& data,
                         std::optional<u64> process_id = {}, std::optional<u128> user_id = {}) const;
 
     // Used by error applet