[PATCH v9 3/4] drm/xe/guc: Add capture size check in GuC log buffer

Dong, Zhanjun zhanjun.dong at intel.com
Wed Jun 19 22:56:07 UTC 2024



On 2024-06-19 6:28 p.m., Michal Wajdeczko wrote:
> 
> 
> On 19.06.2024 21:44, Dong, Zhanjun wrote:
>> Please see my comments inline below.
>>
>> Zhanjun
>>
>> On 2024-06-14 8:13 a.m., Michal Wajdeczko wrote:
>>>
>>>
>>> On 07.06.2024 02:07, Zhanjun Dong wrote:
>>>> The capture-nodes is included in GuC log buffer, add the size check
>>>> for capture region in the whole GuC log buffer.
>>>> Add capture output size check before allocating the shared buffer.
>>>>
>>>> Signed-off-by: Zhanjun Dong <zhanjun.dong at intel.com>
>>>> ---
>>>>    drivers/gpu/drm/xe/xe_gt_printk.h     |   3 +
...

>>>> diff --git a/drivers/gpu/drm/xe/xe_guc_fwif.h
>>>> b/drivers/gpu/drm/xe/xe_guc_fwif.h
>>>> index 04b03c398191..908298791c93 100644
>>>> --- a/drivers/gpu/drm/xe/xe_guc_fwif.h
>>>> +++ b/drivers/gpu/drm/xe/xe_guc_fwif.h
>>>> @@ -250,6 +250,54 @@ struct guc_engine_usage {
>>>>        struct guc_engine_usage_record
>>>> engines[GUC_MAX_ENGINE_CLASSES][GUC_MAX_INSTANCES_PER_CLASS];
>>>>    } __packed;
>>>>    +/* GuC logging structures */
>>>> +
>>>> +enum guc_log_buffer_type {
>>>> +    GUC_DEBUG_LOG_BUFFER,
>>>> +    GUC_CRASH_DUMP_LOG_BUFFER,
>>>> +    GUC_CAPTURE_LOG_BUFFER,
>>>> +    GUC_MAX_LOG_BUFFER
>>>
>>> this last enumerator is not real buffer type, so better at least name it
>>> in a different way (at least add __ prefix?
>>>
>>> or best, since it looks like ABI definitions, just move it out of the
>>> enum to benefit from compiler checks that John prefers:
>>>
>>> enum guc_log_buffer_type {
>>>      GUC_LOG_BUFFER_DEBUG        = 0,
>>>      GUC_LOG_BUFFER_CRASH_DUMP    = 1,
>>>      GUC_LOG_BUFFER_CAPTURE_LOG    = 2,
>>> };
>>> #define NUM_GUC_LOG_BUFFER_TYPES    3
>>>
>> Will changed to:
>> /* GuC logging structures */
>> enum guc_log_buffer_type {
>>      GUC_DEBUG_LOG_BUFFER,
>>      GUC_CRASH_DUMP_LOG_BUFFER,
>>      GUC_CAPTURE_LOG_BUFFER,
>>
>>      GUC_LOG_BUFFER_TYPE_MAX
>> };
>> The empty line speprate real type vs MAX
> 
> empty line is not enough to let the compiler see the difference between
> real _type_ and _max_ definition
> 
>> I would prefer to stay within the enum, which make add new type easier,
>> the MAX will be updated by compiler automatically, no need to manually
>> add 1 to NUM_xxx macro.
> 
> but this is (or should be) a stable ABI so we shouldn't rely on the
> compiler to automatically making any changes to any of these defs.
> 
> and as of today we have exactly 3 types defined as:
> 
>      GUC_LOG_BUFFER_DEBUG        = 0,
>      GUC_LOG_BUFFER_CRASH_DUMP    = 1,
>      GUC_LOG_BUFFER_CAPTURE_LOG    = 2,
> 
> so if you want to use enum to get some help from the compiler, like to
> check that in your implementation you are not using bad types, then
> there should be no other enumerators in this enum, as otherwise you kill
> that feature
> 
> also note that your approach will not work if for some reason the new
> type will be defined as something different than 3, like:
> 
>      GUC_LOG_BUFFER_FUTURE    = 345
> 
> so while will have 4 TYPES, your automatic MAX will be 346, making it
> almost useless
That's true, it is a stable ABI.
Will be changed to John style.

> 
>>
>>>> +};
>>>> +
>>>> +/*
>>>> + * struct guc_log_buffer_state - GuC log buffer state
>>>
>>> this is not a kernel-doc format, intentional or typo ?
>>>
>>>> + *
>>>> + * Below state structure is used for coordination of retrieval of
>>>> GuC firmware
>>>> + * logs. Separate state is maintained for each log buffer type.
>>>> + * read_ptr points to the location where Xe read last in log buffer and
>>>> + * is read only for GuC firmware. write_ptr is incremented by GuC
>>>> with number
>>>> + * of bytes written for each log entry and is read only for Xe.
>>>> + * When any type of log buffer becomes half full, GuC sends a flush
>>>> interrupt.
>>>> + * GuC firmware expects that while it is writing to 2nd half of the
>>>> buffer,
>>>> + * first half would get consumed by Host and then get a flush completed
>>>> + * acknowledgment from Host, so that it does not end up doing any
>

...

>>>> +    }
>>>> +
>>>> +    return overflow;
>>>> +}
>>>> +
>>>> +unsigned int xe_guc_get_log_buffer_size(struct xe_guc_log *log,
>>>> +                    enum guc_log_buffer_type type)
>>>> +{
>>>> +    switch (type) {
>>>> +    case GUC_DEBUG_LOG_BUFFER:
>>>> +        return xe_guc_log_section_size_debug(log);
>>>> +    case GUC_CRASH_DUMP_LOG_BUFFER:
>>>> +        return xe_guc_log_section_size_crash(log);
>>>> +    case GUC_CAPTURE_LOG_BUFFER:
>>>> +        return xe_guc_log_section_size_capture(log);
>>>> +    default:
>>>> +        MISSING_CASE(type);
>>>
>>> there should be no need for 'default' case if you properly define your
>>> enum type
>> Compiler could check static error, while 'default' here can cover
>> run-time errors. I would prefer to have it for public funcitons.
> 
> but this is still driver only function, called only from your code,
> where you should be using only valid enumerators, so no need for any
> random runtime protection (unless you already abuse this function by
> using random integers as params)
> 
By switch to John style, this default case could be removed.

> 
>>>
>>>> +    }
>>>> +
>>>> +    return 0;
>>>> +}
>>>> +
>>>> +size_t xe_guc_get_log_buffer_offset(struct xe_guc_log *log,
>>>> +                    enum guc_log_buffer_type type)
>>>> +{
>>>> +    enum guc_log_buffer_type i;
>>>> +    size_t offset = PAGE_SIZE;/* for the log_buffer_states */
>>>> +
>>>> +    for (i = GUC_DEBUG_LOG_BUFFER; i < GUC_MAX_LOG_BUFFER; ++i) {
>>>> +        if (i == type)
>>>> +            break;

...


More information about the Intel-xe mailing list