Another pair of fixes on nvgpu

This commit is contained in:
CamilleLaVey
2026-08-02 03:44:54 -04:00
parent bbb75f8dd4
commit 2215455617
4 changed files with 44 additions and 77 deletions
@@ -375,39 +375,42 @@ NvResult nvhost_as_gpu::MapBufferEx(IoctlMapBufferEx& params) {
mapping_map.insert_or_assign(params.offset, Mapping(params.handle, device_address, params.offset, size, false, big_page, false));
}
map_buffer_offsets.insert(params.offset);
return NvResult::Success;
}
NvResult nvhost_as_gpu::UnmapBuffer(IoctlUnmapBuffer& params) {
LOG_DEBUG(Service_NVDRV, "called, offset={:#X}", params.offset);
std::scoped_lock lock(mutex);
if (auto const offset_it = map_buffer_offsets.find(params.offset); offset_it != map_buffer_offsets.end()) {
LOG_DEBUG(Service_NVDRV, "called, offset={:#X}", params.offset);
if (!vm.initialised) {
return NvResult::BadValue;
}
auto const it = mapping_map.find(params.offset);
auto const mapping = it->second;
if (!mapping.fixed) {
auto& allocator{mapping.big_page ? *vm.big_page_allocator : *vm.small_page_allocator};
u32 page_size_bits{mapping.big_page ? vm.big_page_size_bits : VM::PAGE_SIZE_BITS};
allocator.Free(u32(mapping.offset >> page_size_bits), u32(mapping.size >> page_size_bits));
}
// Sparse mappings shouldn't be fully unmapped, just returned to their sparse state
// Only FreeSpace can unmap them fully
if (mapping.sparse_alloc) {
gmmu->MapSparse(params.offset, mapping.size, mapping.big_page);
} else {
gmmu->Unmap(params.offset, mapping.size);
}
nvmap.UnpinHandle(mapping.handle);
mapping_map.erase(params.offset);
map_buffer_offsets.erase(params.offset);
if (!vm.initialised) {
return NvResult::BadValue;
}
auto const it = mapping_map.find(params.offset);
if (it == mapping_map.end()) {
LOG_WARNING(Service_NVDRV, "Couldn't find region to unmap at {:#X}", params.offset);
return NvResult::Success;
}
auto const mapping = it->second;
if (!mapping.fixed) {
auto& allocator{mapping.big_page ? *vm.big_page_allocator : *vm.small_page_allocator};
u32 page_size_bits{mapping.big_page ? vm.big_page_size_bits : VM::PAGE_SIZE_BITS};
allocator.Free(u32(mapping.offset >> page_size_bits), u32(mapping.size >> page_size_bits));
}
// Sparse mappings shouldn't be fully unmapped, just returned to their sparse state
// Only FreeSpace can unmap them fully
if (mapping.sparse_alloc) {
gmmu->MapSparse(params.offset, mapping.size, mapping.big_page);
} else {
gmmu->Unmap(params.offset, mapping.size);
}
nvmap.UnpinHandle(mapping.handle);
mapping_map.erase(it);
return NvResult::Success;
}
@@ -13,7 +13,6 @@
#include <memory>
#include <mutex>
#include <optional>
#include <ankerl/unordered_dense.h>
#include <vector>
#include "common/address_space.h"
@@ -113,8 +112,6 @@ private:
};
static_assert(sizeof(IoctlRemapEntry) == 20, "IoctlRemapEntry is incorrect size");
ankerl::unordered_dense::set<s64_le> map_buffer_offsets{};
struct IoctlMapBufferEx {
MappingFlags flags{}; // bit0: fixed_offset, bit2: cacheable
u32_le kind{}; // -1 is default
@@ -174,7 +174,9 @@ NvResult nvhost_gpu::SetChannelPriority(IoctlChannelSetPriority& params) {
case ChannelPriority::Low: channel_timeslice = 1300; break;
case ChannelPriority::Medium: channel_timeslice = 2600; break;
case ChannelPriority::High: channel_timeslice = 5200; break;
default : return NvResult::BadParameter;
default:
LOG_WARNING(Service_NVDRV, "unknown channel priority {:#X}", channel_priority);
break;
}
return NvResult::Success;
@@ -278,18 +280,20 @@ NvResult nvhost_gpu::AllocateObjectContext(IoctlAllocObjCtx& params) {
params.flags = allowed_mask;
}
s32_le ctx_class_number_index =
params.obj_id = 0;
s32_le ctx_class_number_index =
GetObjectContextClassNumberIndex(static_cast<CtxClasses>(params.class_num));
if (ctx_class_number_index < 0) {
LOG_ERROR(Service_NVDRV, "Invalid class number for object context: {:#X}",
params.class_num);
return NvResult::BadParameter;
LOG_WARNING(Service_NVDRV, "Untracked class number for object context: {:#X}",
params.class_num);
return NvResult::Success;
}
if (ctxObjs[ctx_class_number_index].has_value()) {
LOG_WARNING(Service_NVDRV, "Object context for class {:#X} already allocated on this channel",
params.class_num);
return NvResult::AlreadyAllocated;
LOG_DEBUG(Service_NVDRV, "Object context for class {:#X} already allocated on this channel",
params.class_num);
return NvResult::Success;
}
// Defer actual hardware context binding until channel is initialized.
@@ -435,10 +439,6 @@ NvResult nvhost_gpu::ChannelSetTimeout(IoctlChannelSetTimeout& params) {
NvResult nvhost_gpu::ChannelSetTimeslice(IoctlSetTimeslice& params) {
LOG_INFO(Service_NVDRV, "called, timeslice={:#X}", params.timeslice);
if (params.timeslice < 1000 || params.timeslice > 5000) {
return NvResult::BadParameter;
}
channel_timeslice = params.timeslice;
return NvResult::Success;
@@ -17,28 +17,12 @@ enum class Mode : u64 {
Attr,
};
enum class SZ : u64 {
U8,
U16,
U32,
F32
};
enum class Shift : u64 {
Default,
U16,
B32,
};
IR::U32 scaleIndex(IR::IREmitter& ir, IR::U32 index, Shift shift) {
switch (shift) {
case Shift::Default: return index;
case Shift::U16: return ir.ShiftLeftLogical(index, ir.Imm32(1));
case Shift::B32: return ir.ShiftLeftLogical(index, ir.Imm32(2));
default: UNREACHABLE();
}
}
} // Anonymous namespace
void TranslatorVisitor::ISBERD(u64 insn) {
@@ -53,7 +37,6 @@ void TranslatorVisitor::ISBERD(u64 insn) {
BitField<31, 1, u64> skew;
BitField<32, 1, u64> o;
BitField<33, 2, Mode> mode;
BitField<36, 4, SZ> sz;
BitField<47, 2, Shift> shift;
} const isberd{insn};
@@ -63,31 +46,15 @@ void TranslatorVisitor::ISBERD(u64 insn) {
if (isberd.o != 0) {
throw NotImplementedException("ISBERD O");
}
if (isberd.sz.Value() > SZ::F32) {
throw NotImplementedException("ISBERD SZ {}",
static_cast<u64>(isberd.sz.Value()));
}
if (isberd.shift.Value() > Shift::B32) {
throw NotImplementedException("ISBERD Shift {}",
static_cast<u64>(isberd.shift.Value()));
}
switch (isberd.mode.Value()) {
case Mode::Default:
X(isberd.dest_reg.Value(), X(isberd.src_reg.Value()));
return;
case Mode::Attr: {
IR::U32 offset{};
if (isberd.src_reg_num.Value() == 0xFF) {
offset = ir.Imm32(isberd.imm.Value());
} else {
const IR::U32 index{
scaleIndex(ir, X(isberd.src_reg.Value()), isberd.shift.Value())};
offset = ir.IAdd(index, ir.Imm32(isberd.imm.Value()));
}
X(isberd.dest_reg.Value(), ir.BitCast<IR::U32>(ir.GetAttributeIndexed(offset)));
case Mode::Attr:
LOG_DEBUG(Shader, "(STUBBED) ISBERD Mode Attr");
X(isberd.dest_reg.Value(), X(isberd.src_reg.Value()));
return;
}
default:
throw NotImplementedException("ISBERD Mode {}",
static_cast<u64>(isberd.mode.Value()));