GPU: Implemented the nvmap Free ioctl.
It releases a reference to an nvmap object
This commit is contained in:
		@@ -30,6 +30,8 @@ u32 nvmap::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& o
 | 
				
			|||||||
        return IocFromId(input, output);
 | 
					        return IocFromId(input, output);
 | 
				
			||||||
    case IoctlCommand::Param:
 | 
					    case IoctlCommand::Param:
 | 
				
			||||||
        return IocParam(input, output);
 | 
					        return IocParam(input, output);
 | 
				
			||||||
 | 
					    case IoctlCommand::Free:
 | 
				
			||||||
 | 
					        return IocFree(input, output);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    UNIMPLEMENTED_MSG("Unimplemented ioctl");
 | 
					    UNIMPLEMENTED_MSG("Unimplemented ioctl");
 | 
				
			||||||
@@ -45,6 +47,7 @@ u32 nvmap::IocCreate(const std::vector<u8>& input, std::vector<u8>& output) {
 | 
				
			|||||||
    object->id = next_id++;
 | 
					    object->id = next_id++;
 | 
				
			||||||
    object->size = params.size;
 | 
					    object->size = params.size;
 | 
				
			||||||
    object->status = Object::Status::Created;
 | 
					    object->status = Object::Status::Created;
 | 
				
			||||||
 | 
					    object->refcount = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    u32 handle = next_handle++;
 | 
					    u32 handle = next_handle++;
 | 
				
			||||||
    handles[handle] = std::move(object);
 | 
					    handles[handle] = std::move(object);
 | 
				
			||||||
@@ -101,6 +104,8 @@ u32 nvmap::IocFromId(const std::vector<u8>& input, std::vector<u8>& output) {
 | 
				
			|||||||
                            [&](const auto& entry) { return entry.second->id == params.id; });
 | 
					                            [&](const auto& entry) { return entry.second->id == params.id; });
 | 
				
			||||||
    ASSERT(itr != handles.end());
 | 
					    ASSERT(itr != handles.end());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    itr->second->refcount++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Return the existing handle instead of creating a new one.
 | 
					    // Return the existing handle instead of creating a new one.
 | 
				
			||||||
    params.handle = itr->first;
 | 
					    params.handle = itr->first;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -142,4 +147,34 @@ u32 nvmap::IocParam(const std::vector<u8>& input, std::vector<u8>& output) {
 | 
				
			|||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					u32 nvmap::IocFree(const std::vector<u8>& input, std::vector<u8>& output) {
 | 
				
			||||||
 | 
					    enum FreeFlags {
 | 
				
			||||||
 | 
					        Freed = 0,
 | 
				
			||||||
 | 
					        NotFreedYet = 1,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IocFreeParams params;
 | 
				
			||||||
 | 
					    std::memcpy(¶ms, input.data(), sizeof(params));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    NGLOG_WARNING(Service_NVDRV, "(STUBBED) called");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto itr = handles.find(params.handle);
 | 
				
			||||||
 | 
					    ASSERT(itr != handles.end());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    itr->second->refcount--;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    params.refcount = itr->second->refcount;
 | 
				
			||||||
 | 
					    params.size = itr->second->size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (itr->second->refcount == 0)
 | 
				
			||||||
 | 
					        params.flags = Freed;
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        params.flags = NotFreedYet;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    handles.erase(params.handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::memcpy(output.data(), ¶ms, sizeof(params));
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace Service::Nvidia::Devices
 | 
					} // namespace Service::Nvidia::Devices
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,6 +34,7 @@ public:
 | 
				
			|||||||
        u8 kind;
 | 
					        u8 kind;
 | 
				
			||||||
        VAddr addr;
 | 
					        VAddr addr;
 | 
				
			||||||
        Status status;
 | 
					        Status status;
 | 
				
			||||||
 | 
					        u32 refcount;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::shared_ptr<Object> GetObject(u32 handle) const {
 | 
					    std::shared_ptr<Object> GetObject(u32 handle) const {
 | 
				
			||||||
@@ -59,7 +60,8 @@ private:
 | 
				
			|||||||
        FromId = 0xC0080103,
 | 
					        FromId = 0xC0080103,
 | 
				
			||||||
        Alloc = 0xC0200104,
 | 
					        Alloc = 0xC0200104,
 | 
				
			||||||
        Param = 0xC00C0109,
 | 
					        Param = 0xC00C0109,
 | 
				
			||||||
        GetId = 0xC008010E
 | 
					        GetId = 0xC008010E,
 | 
				
			||||||
 | 
					        Free = 0xC0180105,
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    struct IocCreateParams {
 | 
					    struct IocCreateParams {
 | 
				
			||||||
@@ -102,11 +104,21 @@ private:
 | 
				
			|||||||
        u32_le value;
 | 
					        u32_le value;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct IocFreeParams {
 | 
				
			||||||
 | 
					        u32_le handle;
 | 
				
			||||||
 | 
					        INSERT_PADDING_BYTES(4);
 | 
				
			||||||
 | 
					        u64_le refcount;
 | 
				
			||||||
 | 
					        u32_le size;
 | 
				
			||||||
 | 
					        u32_le flags;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    static_assert(sizeof(IocFreeParams) == 24, "IocFreeParams has wrong size");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    u32 IocCreate(const std::vector<u8>& input, std::vector<u8>& output);
 | 
					    u32 IocCreate(const std::vector<u8>& input, std::vector<u8>& output);
 | 
				
			||||||
    u32 IocAlloc(const std::vector<u8>& input, std::vector<u8>& output);
 | 
					    u32 IocAlloc(const std::vector<u8>& input, std::vector<u8>& output);
 | 
				
			||||||
    u32 IocGetId(const std::vector<u8>& input, std::vector<u8>& output);
 | 
					    u32 IocGetId(const std::vector<u8>& input, std::vector<u8>& output);
 | 
				
			||||||
    u32 IocFromId(const std::vector<u8>& input, std::vector<u8>& output);
 | 
					    u32 IocFromId(const std::vector<u8>& input, std::vector<u8>& output);
 | 
				
			||||||
    u32 IocParam(const std::vector<u8>& input, std::vector<u8>& output);
 | 
					    u32 IocParam(const std::vector<u8>& input, std::vector<u8>& output);
 | 
				
			||||||
 | 
					    u32 IocFree(const std::vector<u8>& input, std::vector<u8>& output);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace Service::Nvidia::Devices
 | 
					} // namespace Service::Nvidia::Devices
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user