aboutsummaryrefslogtreecommitdiff
path: root/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h
blob: 507cdac71d312aee3c27b67a67ff89dcf416367d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later

// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include <vector>

#include "common/common_funcs.h"
#include "common/common_types.h"
#include "common/swap.h"
#include "core/hle/service/nvdrv/devices/nvdevice.h"

namespace Service::Nvidia {
class EventInterface;
}

namespace Service::Nvidia::Devices {

class nvhost_ctrl_gpu final : public nvdevice {
public:
    explicit nvhost_ctrl_gpu(Core::System& system_, EventInterface& events_interface_);
    ~nvhost_ctrl_gpu() override;

    NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
                    std::span<u8> output) override;
    NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
                    std::span<const u8> inline_input, std::span<u8> output) override;
    NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output,
                    std::span<u8> inline_output) override;

    void OnOpen(NvCore::SessionId session_id, DeviceFD fd) override;
    void OnClose(DeviceFD fd) override;

    Kernel::KEvent* QueryEvent(u32 event_id) override;

private:
    enum class ZBCTypes {
        color = 1,
        depth = 2,
    };

    struct IoctlGpuCharacteristics {
        u32_le arch;                       // 0x120 (NVGPU_GPU_ARCH_GM200)
        u32_le impl;                       // 0xB (NVGPU_GPU_IMPL_GM20B)
        u32_le rev;                        // 0xA1 (Revision A1)
        u32_le num_gpc;                    // 0x1
        u64_le l2_cache_size;              // 0x40000
        u64_le on_board_video_memory_size; // 0x0 (not used)
        u32_le num_tpc_per_gpc;            // 0x2
        u32_le bus_type;                   // 0x20 (NVGPU_GPU_BUS_TYPE_AXI)
        u32_le big_page_size;              // 0x20000
        u32_le compression_page_size;      // 0x20000
        u32_le pde_coverage_bit_count;     // 0x1B
        u32_le available_big_page_sizes;   // 0x30000
        u32_le gpc_mask;                   // 0x1
        u32_le sm_arch_sm_version;         // 0x503 (Maxwell Generation 5.0.3?)
        u32_le sm_arch_spa_version;        // 0x503 (Maxwell Generation 5.0.3?)
        u32_le sm_arch_warp_count;         // 0x80
        u32_le gpu_va_bit_count;           // 0x28
        u32_le reserved;                   // NULL
        u64_le flags;                      // 0x55
        u32_le twod_class;                 // 0x902D (FERMI_TWOD_A)
        u32_le threed_class;               // 0xB197 (MAXWELL_B)
        u32_le compute_class;              // 0xB1C0 (MAXWELL_COMPUTE_B)
        u32_le gpfifo_class;               // 0xB06F (MAXWELL_CHANNEL_GPFIFO_A)
        u32_le inline_to_memory_class;     // 0xA140 (KEPLER_INLINE_TO_MEMORY_B)
        u32_le dma_copy_class;             // 0xB0B5 (MAXWELL_DMA_COPY_A)
        u32_le max_fbps_count;             // 0x1
        u32_le fbp_en_mask;                // 0x0 (disabled)
        u32_le max_ltc_per_fbp;            // 0x2
        u32_le max_lts_per_ltc;            // 0x1
        u32_le max_tex_per_tpc;            // 0x0 (not supported)
        u32_le max_gpc_count;              // 0x1
        u32_le rop_l2_en_mask_0;           // 0x21D70 (fuse_status_opt_rop_l2_fbp_r)
        u32_le rop_l2_en_mask_1;           // 0x0
        u64_le chipname;                   // 0x6230326D67 ("gm20b")
        u64_le gr_compbit_store_base_hw;   // 0x0 (not supported)
    };
    static_assert(sizeof(IoctlGpuCharacteristics) == 160,
                  "IoctlGpuCharacteristics is incorrect size");

    struct IoctlCharacteristics {
        u64_le gpu_characteristics_buf_size; // must not be NULL, but gets overwritten with
                                             // 0xA0=max_size
        u64_le gpu_characteristics_buf_addr; // ignored, but must not be NULL
        IoctlGpuCharacteristics gc;
    };
    static_assert(sizeof(IoctlCharacteristics) == 16 + sizeof(IoctlGpuCharacteristics),
                  "IoctlCharacteristics is incorrect size");

    struct IoctlGpuGetTpcMasksArgs {
        u32_le mask_buffer_size{};
        INSERT_PADDING_WORDS(1);
        u64_le mask_buffer_address{};
        u32_le tcp_mask{};
        INSERT_PADDING_WORDS(1);
    };
    static_assert(sizeof(IoctlGpuGetTpcMasksArgs) == 24,
                  "IoctlGpuGetTpcMasksArgs is incorrect size");

    struct IoctlActiveSlotMask {
        u32_le slot; // always 0x07
        u32_le mask;
    };
    static_assert(sizeof(IoctlActiveSlotMask) == 8, "IoctlActiveSlotMask is incorrect size");

    struct IoctlZcullGetCtxSize {
        u32_le size;
    };
    static_assert(sizeof(IoctlZcullGetCtxSize) == 4, "IoctlZcullGetCtxSize is incorrect size");

    struct IoctlNvgpuGpuZcullGetInfoArgs {
        u32_le width_align_pixels;
        u32_le height_align_pixels;
        u32_le pixel_squares_by_aliquots;
        u32_le aliquot_total;
        u32_le region_byte_multiplier;
        u32_le region_header_size;
        u32_le subregion_header_size;
        u32_le subregion_width_align_pixels;
        u32_le subregion_height_align_pixels;
        u32_le subregion_count;
    };
    static_assert(sizeof(IoctlNvgpuGpuZcullGetInfoArgs) == 40,
                  "IoctlNvgpuGpuZcullGetInfoArgs is incorrect size");

    struct IoctlZbcSetTable {
        u32_le color_ds[4];
        u32_le color_l2[4];
        u32_le depth;
        u32_le format;
        u32_le type;
    };
    static_assert(sizeof(IoctlZbcSetTable) == 44, "IoctlZbcSetTable is incorrect size");

    struct IoctlZbcQueryTable {
        u32_le color_ds[4];
        u32_le color_l2[4];
        u32_le depth;
        u32_le ref_cnt;
        u32_le format;
        u32_le type;
        u32_le index_size;
    };
    static_assert(sizeof(IoctlZbcQueryTable) == 52, "IoctlZbcQueryTable is incorrect size");

    struct ZbcColorEntry {
        std::array<u32, 4> color_ds{};
        std::array<u32, 4> color_l2{};
        u32 format{};
        u32 ref_cnt{};
    };
    static_assert(sizeof(ZbcColorEntry) == 40, "ZbcColorEntry is incorrect size");

    struct ZbcDepthEntry {
        u32 depth{};
        u32 format{};
        u32 ref_cnt{};
    };
    static_assert(sizeof(ZbcDepthEntry) == 12, "ZbcDepthEntry is incorrect size");

    struct IoctlFlushL2 {
        u32_le flush; // l2_flush | l2_invalidate << 1 | fb_flush << 2
        u32_le reserved;
    };
    static_assert(sizeof(IoctlFlushL2) == 8, "IoctlFlushL2 is incorrect size");

    struct IoctlGetGpuTime {
        u64_le gpu_time{};
        INSERT_PADDING_WORDS(2);
    };
    static_assert(sizeof(IoctlGetGpuTime) == 0x10, "IoctlGetGpuTime is incorrect size");

    struct IoctlGetCpuTimeCorrelationInfo {
        struct {
            u64_le cpu_timestamp;
            u64_le gpu_timestamp;
        } samples[16];
        u32_le count;
        u32_le source_id;
    };
    static_assert(sizeof(IoctlGetCpuTimeCorrelationInfo) == 264);

    struct IoctlPmuGetLoad {
        u32 pmu_gpu_load;
    };
    static_assert(sizeof(IoctlPmuGetLoad) == 4);

    NvResult GetCharacteristics1(IoctlCharacteristics& params);
    NvResult GetCharacteristics3(IoctlCharacteristics& params,
                                 std::span<IoctlGpuCharacteristics> gpu_characteristics);

    NvResult GetTPCMasks1(IoctlGpuGetTpcMasksArgs& params);
    NvResult GetTPCMasks3(IoctlGpuGetTpcMasksArgs& params, std::span<u32> tpc_mask);

    NvResult GetActiveSlotMask(IoctlActiveSlotMask& params);
    NvResult PmuGetGpuLoad(IoctlPmuGetLoad& params);
    NvResult ZCullGetCtxSize(IoctlZcullGetCtxSize& params);
    NvResult ZCullGetInfo(IoctlNvgpuGpuZcullGetInfoArgs& params);
    NvResult ZBCSetTable(IoctlZbcSetTable& params);
    NvResult ZBCQueryTable(IoctlZbcQueryTable& params);
    NvResult FlushL2(IoctlFlushL2& params);
    NvResult GetGpuTime(IoctlGetGpuTime& params);

    EventInterface& events_interface;

    // Events
    NvResult Nx2GetEngineInfo(std::span<const u8> input, std::span<u8> output,
                              std::span<u8> inline_output);

    // Set once a caller asked for the Switch 2 characteristics layout.
    bool nx2_caller{};
    Kernel::KEvent* error_notifier_event;
    Kernel::KEvent* unknown_event;

    // ZBC Tables
    std::mutex zbc_mutex{};
    std::vector<ZbcColorEntry> zbc_colors{};
    std::vector<ZbcDepthEntry> zbc_depths{};
    const u32 supported_types = 2u;
};

} // namespace Service::Nvidia::Devices