/* Each region is a minimum of 16k, and there are at most 255 of them.
*/ #define I915_NR_TEX_REGIONS 255/* table size 2k - maximum due to use
* of chars for next/prev indices */ #define I915_LOG_MIN_TEX_REGION_SIZE 14
typedefstruct _drm_i915_sarea { struct drm_tex_region texList[I915_NR_TEX_REGIONS + 1]; int last_upload; /* last time texture was uploaded */ int last_enqueue; /* last time a buffer was enqueued */ int last_dispatch; /* age of the most recently dispatched buffer */ int ctxOwner; /* last context to upload state */ int texAge; int pf_enabled; /* is pageflipping allowed? */ int pf_active; int pf_current_page; /* which buffer is being displayed? */ int perf_boxes; /* performance boxes to be displayed */ int width, height; /* screen size in pixels */
drm_handle_t front_handle; int front_offset; int front_size;
drm_handle_t back_handle; int back_offset; int back_size;
drm_handle_t depth_handle; int depth_offset; int depth_size;
drm_handle_t tex_handle; int tex_offset; int tex_size; int log_tex_granularity; int pitch; int rotation; /* 0, 90, 180 or 270 */ int rotated_offset; int rotated_size; int rotated_pitch; int virtualX, virtualY;
int pipeA_x; int pipeA_y; int pipeA_w; int pipeA_h; int pipeB_x; int pipeB_y; int pipeB_w; int pipeB_h;
/* fill out some space for old userspace triple buffer */
drm_handle_t unused_handle;
__u32 unused1, unused2, unused3;
/* buffer object handles for static buffers. May change *overthelifetimeoftheclient.
*/
__u32 front_bo_handle;
__u32 back_bo_handle;
__u32 unused_bo_handle;
__u32 depth_bo_handle;
} drm_i915_sarea_t;
/* due to userspace building against these headers we need some compat here */ #define planeA_x pipeA_x #define planeA_y pipeA_y #define planeA_w pipeA_w #define planeA_h pipeA_h #define planeB_x pipeB_x #define planeB_y pipeB_y #define planeB_w pipeB_w #define planeB_h pipeB_h
/* Allow drivers to submit batchbuffers directly to hardware, relying *onthesecuritymechanismsprovidedbyhardware.
*/ typedefstruct drm_i915_batchbuffer { int start; /* agp offset */ int used; /* nr bytes in use */ int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */ int DR4; /* window origin for GFX_OP_DRAWRECT_INFO */ int num_cliprects; /* mulitpass with multiple cliprects? */ struct drm_clip_rect __user *cliprects; /* pointer to userspace cliprects */
} drm_i915_batchbuffer_t;
/* As above, but pass a pointer to userspace buffer which can be *validatedbythekernelpriortosendingtohardware.
*/ typedefstruct _drm_i915_cmdbuffer { char __user *buf; /* pointer to userspace command buffer */ int sz; /* nr bytes in buf */ int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */ int DR4; /* window origin for GFX_OP_DRAWRECT_INFO */ int num_cliprects; /* mulitpass with multiple cliprects? */ struct drm_clip_rect __user *cliprects; /* pointer to userspace cliprects */
} drm_i915_cmdbuffer_t;
/* Userspace can request & wait on irq's:
*/ typedefstruct drm_i915_irq_emit { int __user *irq_seq;
} drm_i915_irq_emit_t;
typedefstruct drm_i915_irq_wait { int irq_seq;
} drm_i915_irq_wait_t;
/* Frequency of the command streamer timestamps given by the *_TIMESTAMP *registers.ThisusedtobefixedperplatformbutfromCNLonwards,this *mightvarydependingontheparts.
*/ #define I915_PARAM_CS_TIMESTAMP_FREQUENCY 51
/* Ioctl to set kernel params:
*/ #define I915_SETPARAM_USE_MI_BATCHBUFFER_START 1 #define I915_SETPARAM_TEX_LRU_LOG_GRANULARITY 2 #define I915_SETPARAM_ALLOW_BATCHBUFFER 3 #define I915_SETPARAM_NUM_USED_FENCES 4 /* Must be kept compact -- no holes */
typedefstruct drm_i915_setparam { int param; int value;
} drm_i915_setparam_t;
/* A memory manager for regions of shared memory:
*/ #define I915_MEM_REGION_AGP 1
typedefstruct drm_i915_mem_alloc { int region; int alignment; int size; int __user *region_offset; /* offset from start of fb or agp */
} drm_i915_mem_alloc_t;
typedefstruct drm_i915_mem_free { int region; int region_offset;
} drm_i915_mem_free_t;
typedefstruct drm_i915_mem_init_heap { int region; int size; int start;
} drm_i915_mem_init_heap_t;
/* Allow memory manager to be torn down and re-initialized (eg on *rotate):
*/ typedefstruct drm_i915_mem_destroy_heap { int region;
} drm_i915_mem_destroy_heap_t;
/* Allow X server to configure which pipes to monitor for vblank signals
*/ #define DRM_I915_VBLANK_PIPE_A 1 #define DRM_I915_VBLANK_PIPE_B 2
typedefstruct drm_i915_vblank_pipe { int pipe;
} drm_i915_vblank_pipe_t;
struct drm_i915_gem_pread { /** Handle for the object being read. */
__u32 handle;
__u32 pad; /** Offset into the object to read from */
__u64 offset; /** Length of data to read */
__u64 size; /** *Pointertowritethedatainto. * *Thisisafixed-sizetypefor32/64compatibility.
*/
__u64 data_ptr;
};
struct drm_i915_gem_pwrite { /** Handle for the object being written to. */
__u32 handle;
__u32 pad; /** Offset into the object to write to */
__u64 offset; /** Length of data to write */
__u64 size; /** *Pointertoreadthedatafrom. * *Thisisafixed-sizetypefor32/64compatibility.
*/
__u64 data_ptr;
};
struct drm_i915_gem_mmap { /** Handle for the object being mapped. */
__u32 handle;
__u32 pad; /** Offset in the object to map. */
__u64 offset; /** *Lengthofdatatomap. * *Thevaluewillbepage-aligned.
*/
__u64 size; /** *Returnedpointerthedatawasmappedat. * *Thisisafixed-sizetypefor32/64compatibility.
*/
__u64 addr_ptr;
/** Number of relocations to be performed on this buffer */
__u32 relocation_count; /** *Pointertoarrayofstructdrm_i915_gem_relocation_entrycontaining *therelocationstobeperformedinthisbuffer.
*/
__u64 relocs_ptr;
/** Required alignment in graphics aperture */
__u64 alignment;
/* DRM_IOCTL_I915_GEM_EXECBUFFER was removed in Linux 5.13 */ struct drm_i915_gem_execbuffer { /** *Listofbufferstobevalidatedwiththeirrelocationstobe *performendonthem. * *Thisisapointertoanarrayofstructdrm_i915_gem_validate_entry. * *Thesebuffersmustbelistedinanordersuchthatallrelocations *abufferisperformingrefertobuffersthathavealreadyappeared *inthevalidatelist.
*/
__u64 buffers_ptr;
__u32 buffer_count;
/** Offset in the batchbuffer to start execution from. */
__u32 batch_start_offset; /** Bytes used in batchbuffer from batch_start_offset */
__u32 batch_len;
__u32 DR1;
__u32 DR4;
__u32 num_cliprects; /** This is a struct drm_clip_rect *cliprects */
__u64 cliprects_ptr;
};
/** Number of relocations to be performed on this buffer */
__u32 relocation_count; /** *Pointertoarrayofstructdrm_i915_gem_relocation_entrycontaining *therelocationstobeperformedinthisbuffer.
*/
__u64 relocs_ptr;
/** Required alignment in graphics aperture */
__u64 alignment;
/* *I915_CONTEXT_PARAM_CONTEXT_IMAGE: * *Allowsuserspacetoprovideowncontextimages. * *NotethatthisisadebugAPInotavailableonproductionkernelbuilds.
*/
#define I915_CONTEXT_PARAM_CONTEXT_IMAGE 0xf /* Must be kept compact -- no holes and well documented */
/** @value: Context parameter value to be set or queried */
__u64 value;
};
/** *DOC:VirtualEngineuAPI * *Virtualengineisaconceptwhereuserspaceisabletoconfigureasetof *physicalengines,submitabatchbuffer,andletthedriverexecuteitonany *enginefromthesetasitseesfit. * *Thisisprimarilyusefulonpartswhichhavemultipleinstancesofasame *classengine,likeforexampleGT3+SkylakepartswiththeirtwoVCSengines. * *Forinstanceuserspacecanenumerateallenginesofacertainclassusingthe *previouslydescribed`EngineDiscoveryuAPI`_.Afterthatuserspacecan *createaGEMcontextwithaplaceholderslotforthevirtualengine(using *`I915_ENGINE_CLASS_INVALID`and`I915_ENGINE_CLASS_INVALID_NONE`forclass *andinstancerespectively)andfinallyusingthe *`I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE`extensionplaceavirtualenginein *thesamereservedslot. * *Exampleofcreatingavirtualengineandsubmittingabatchbuffertoit: * *..code-block::C * *I915_DEFINE_CONTEXT_ENGINES_LOAD_BALANCE(virtual,2)={ *.base.name=I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE, *.engine_index=0,// Place this virtual engine into engine map slot 0 *.num_siblings=2, *.engines={{I915_ENGINE_CLASS_VIDEO,0}, *{I915_ENGINE_CLASS_VIDEO,1},}, *}; *I915_DEFINE_CONTEXT_PARAM_ENGINES(engines,1)={ *.engines={{I915_ENGINE_CLASS_INVALID, *I915_ENGINE_CLASS_INVALID_NONE}}, *.extensions=to_user_pointer(&virtual),// Chains after load_balance extension *}; *structdrm_i915_gem_context_create_ext_setparamp_engines={ *.base={ *.name=I915_CONTEXT_CREATE_EXT_SETPARAM, *}, *.param={ *.param=I915_CONTEXT_PARAM_ENGINES, *.value=to_user_pointer(&engines), *.size=sizeof(engines), *}, *}; *structdrm_i915_gem_context_create_extcreate={ *.flags=I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS, *.extensions=to_user_pointer(&p_engines); *}; * *ctx_id=gem_context_create_ext(drm_fd,&create); * *// Now we have created a GEM context with its engine map containing a *// single virtual engine. Submissions to this slot can go either to *// vcs0 or vcs1, depending on the load balancing algorithm used inside *// the driver. The load balancing is dynamic from one batch buffer to *// another and transparent to userspace. * *... *execbuf.rsvd1=ctx_id; *execbuf.flags=0;// Submits to index 0 which is the virtual engine *gem_execbuf(drm_fd,&execbuf);
*/
/** *DOC:ContextEngineMapuAPI * *Contextenginemapisanewwayofaddressingengineswhensubmittingbatch- *buffers,replacingtheexistingwayofusingidentifierslike`I915_EXEC_BLT` *insidetheflagsfieldof`structdrm_i915_gem_execbuffer2`. * *TouseitcreatedGEMcontextsneedtobeconfiguredwithalistofengines *theuserisintendingtosubmitto.Thisisaccomplishedusingthe *`I915_CONTEXT_PARAM_ENGINES`parameterand`struct *i915_context_param_engines`. * *Forsuchcontextsthe`I915_EXEC_RING_MASK`fieldbecomesanindexintothe *configuredmap. * *Exampleofcreatingsuchcontextandsubmittingagainstit: * *..code-block::C * *I915_DEFINE_CONTEXT_PARAM_ENGINES(engines,2)={ *.engines={{I915_ENGINE_CLASS_RENDER,0}, *{I915_ENGINE_CLASS_COPY,0}} *}; *structdrm_i915_gem_context_create_ext_setparamp_engines={ *.base={ *.name=I915_CONTEXT_CREATE_EXT_SETPARAM, *}, *.param={ *.param=I915_CONTEXT_PARAM_ENGINES, *.value=to_user_pointer(&engines), *.size=sizeof(engines), *}, *}; *structdrm_i915_gem_context_create_extcreate={ *.flags=I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS, *.extensions=to_user_pointer(&p_engines); *}; * *ctx_id=gem_context_create_ext(drm_fd,&create); * *// We have now created a GEM context with two engines in the map: *// Index 0 points to rcs0 while index 1 points to bcs0. Other engines *// will not be accessible from this context. * *... *execbuf.rsvd1=ctx_id; *execbuf.flags=0;// Submits to index 0, which is rcs0 for this context *gem_execbuf(drm_fd,&execbuf); * *... *execbuf.rsvd1=ctx_id; *execbuf.flags=1;// Submits to index 0, which is bcs0 for this context *gem_execbuf(drm_fd,&execbuf);
*/
struct i915_context_param_engines {
__u64 extensions; /* linked chain of extension blocks, 0 terminates */
#define I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE 0/* see i915_context_engines_load_balance */
#define I915_CONTEXT_ENGINES_EXT_BOND 1/* see i915_context_engines_bond */
#define I915_CONTEXT_ENGINES_EXT_PARALLEL_SUBMIT 2/* see i915_context_engines_parallel_submit */
struct i915_engine_class_instance engines[];
} __attribute__((packed));
/**
* @user_size:
*
* The size in bytes for the allocated memory. This will also become the
* object size.
*
* Needs to be aligned to PAGE_SIZE, and should be at least PAGE_SIZE,
* or larger.
*/
__u64 user_size;
/**
* @flags:
*
* Supported flags:
*
* I915_USERPTR_READ_ONLY:
*
* Mark the object as readonly, this also means GPU access can only be
* readonly. This is only supported on HW which supports readonly access
* through the GTT. If the HW can't support readonly access, an error is
* returned.
*
* I915_USERPTR_PROBE:
*
* Probe the provided @user_ptr range and validate that the @user_ptr is
* indeed pointing to normal memory and that the range is also valid.
* For example if some garbage address is given to the kernel, then this
* should complain.
*
* Returns -EFAULT if the probe failed.
*
* Note that this doesn't populate the backing pages, and also doesn't
* guarantee that the object will remain valid when the object is
* eventually used.
*
* The kernel supports this feature if I915_PARAM_HAS_USERPTR_PROBE
* returns a non-zero value.
*
* I915_USERPTR_UNSYNCHRONIZED:
*
* NOT USED. Setting this flag will result in an error.
*/
__u32 flags;
#define I915_USERPTR_READ_ONLY 0x1
#define I915_USERPTR_PROBE 0x2
#define I915_USERPTR_UNSYNCHRONIZED 0x80000000
/**
* @handle: Returned handle for the object.
*
* Object handles are nonzero.
*/
__u32 handle;
};
enum drm_i915_oa_format {
I915_OA_FORMAT_A13 = 1, /* HSW only */
I915_OA_FORMAT_A29, /* HSW only */
I915_OA_FORMAT_A13_B8_C8, /* HSW only */
I915_OA_FORMAT_B4_C8, /* HSW only */
I915_OA_FORMAT_A45_B8_C8, /* HSW only */
I915_OA_FORMAT_B4_C8_A16, /* HSW only */
I915_OA_FORMAT_C4_B8, /* HSW+ */
enum drm_i915_perf_property_id {
/**
* Open the stream for a specific context handle (as used with
* execbuffer2). A stream opened for a specific context this way
* won't typically require root privileges.
*
* This property is available in perf revision 1.
*/
DRM_I915_PERF_PROP_CTX_HANDLE = 1,
/**
* A value of 1 requests the inclusion of raw OA unit reports as
* part of stream samples.
*
* This property is available in perf revision 1.
*/
DRM_I915_PERF_PROP_SAMPLE_OA,
/**
* The value specifies which set of OA unit metrics should be
* configured, defining the contents of any OA unit reports.
*
* This property is available in perf revision 1.
*/
DRM_I915_PERF_PROP_OA_METRICS_SET,
/**
* The value specifies the size and layout of OA unit reports.
*
* This property is available in perf revision 1.
*/
DRM_I915_PERF_PROP_OA_FORMAT,
/**
* Specifying this property implicitly requests periodic OA unit
* sampling and (at least on Haswell) the sampling frequency is derived
* from this exponent as follows:
*
* 80ns * 2^(period_exponent + 1)
*
* This property is available in perf revision 1.
*/
DRM_I915_PERF_PROP_OA_EXPONENT,
/**
* Specifying this property is only valid when specify a context to
* filter with DRM_I915_PERF_PROP_CTX_HANDLE. Specifying this property
* will hold preemption of the particular context we want to gather
* performance data about. The execbuf2 submissions must include a
* drm_i915_gem_execbuffer_ext_perf parameter for this to apply.
*
* This property is available in perf revision 3.
*/
DRM_I915_PERF_PROP_HOLD_PREEMPTION,
/**
* Specifying this pins all contexts to the specified SSEU power
* configuration for the duration of the recording.
*
* This parameter's value is a pointer to a struct
* drm_i915_gem_context_param_sseu.
*
* This property is available in perf revision 4.
*/
DRM_I915_PERF_PROP_GLOBAL_SSEU,
/**
* This optional parameter specifies the timer interval in nanoseconds
* at which the i915 driver will check the OA buffer for available data.
* Minimum allowed value is 100 microseconds. A default value is used by
* the driver if this parameter is not specified. Note that larger timer
* values will reduce cpu consumption during OA perf captures. However,
* excessively large values would potentially result in OA buffer
* overwrites as captures reach end of the OA buffer.
*
* This property is available in perf revision 5.
*/
DRM_I915_PERF_PROP_POLL_OA_PERIOD,
/**
* Multiple engines may be mapped to the same OA unit. The OA unit is
* identified by class:instance of any engine mapped to it.
*
* This parameter specifies the engine class and must be passed along
* with DRM_I915_PERF_PROP_OA_ENGINE_INSTANCE.
*
* This property is available in perf revision 6.
*/
DRM_I915_PERF_PROP_OA_ENGINE_CLASS,
/**
* This parameter specifies the engine instance and must be passed along
* with DRM_I915_PERF_PROP_OA_ENGINE_CLASS.
*
* This property is available in perf revision 6.
*/
DRM_I915_PERF_PROP_OA_ENGINE_INSTANCE,
/** The number of u64 (id, value) pairs */
__u32 num_properties;
/**
* Pointer to array of u64 (id, value) pairs configuring the stream
* to open.
*/
__u64 properties_ptr;
};
/*
* Enable data capture for a stream that was either opened in a disabled state
* via I915_PERF_FLAG_DISABLED or was later disabled via
* I915_PERF_IOCTL_DISABLE.
*
* It is intended to be cheaper to disable and enable a stream than it may be
* to close and re-open a stream with the same configuration.
*
* It's undefined whether any pending data for the stream will be lost.
*
* This ioctl is available in perf revision 1.
*/
#define I915_PERF_IOCTL_ENABLE _IO('i', 0x0)
/*
* Disable data capture for a stream.
*
* It is an error to try and read a stream that is disabled.
*
* This ioctl is available in perf revision 1.
*/
#define I915_PERF_IOCTL_DISABLE _IO('i', 0x1)
/*
* Change metrics_set captured by a stream.
*
* If the stream is bound to a specific context, the configuration change
* will performed inline with that context such that it takes effect before
* the next execbuf submission.
*
* Returns the previously bound metrics set id, or a negative error code.
*
* This ioctl is available in perf revision 2.
*/
#define I915_PERF_IOCTL_CONFIG _IO('i', 0x2)
/*
* Common to all i915 perf records
*/
struct drm_i915_perf_record_header {
__u32 type;
__u16 pad;
__u16 size;
};
enum drm_i915_perf_record_type {
/**
* Samples are the work horse record type whose contents are extensible
* and defined when opening an i915 perf stream based on the given
* properties.
*
* Boolean properties following the naming convention
* DRM_I915_PERF_SAMPLE_xyz_PROP request the inclusion of 'xyz' data in
* every sample.
*
* The order of these sample properties given by userspace has no
* affect on the ordering of data within a sample. The order is
* documented here.
*
* struct {
* struct drm_i915_perf_record_header header;
*
* { u32 oa_report[]; } && DRM_I915_PERF_PROP_SAMPLE_OA
* };
*/
DRM_I915_PERF_RECORD_SAMPLE = 1,
/*
* Indicates that one or more OA reports were not written by the
* hardware. This can happen for example if an MI_REPORT_PERF_COUNT
* command collides with periodic sampling - which would be more likely
* at higher sampling frequencies.
*/
DRM_I915_PERF_RECORD_OA_REPORT_LOST = 2,
/**
* An error occurred that resulted in all pending OA reports being lost.
*/
DRM_I915_PERF_RECORD_OA_BUFFER_LOST = 3,
DRM_I915_PERF_RECORD_MAX /* non-ABI */
};
/**
* struct drm_i915_perf_oa_config
*
* Structure to upload perf dynamic configuration into the kernel.
*/
struct drm_i915_perf_oa_config {
/**
* @uuid:
*
* String formatted like "%\08x-%\04x-%\04x-%\04x-%\012x"
*/
char uuid[36];
/**
* @n_mux_regs:
*
* Number of mux regs in &mux_regs_ptr.
*/
__u32 n_mux_regs;
/**
* @n_boolean_regs:
*
* Number of boolean regs in &boolean_regs_ptr.
*/
__u32 n_boolean_regs;
/**
* @n_flex_regs:
*
* Number of flex regs in &flex_regs_ptr.
*/
__u32 n_flex_regs;
/**
* @mux_regs_ptr:
*
* Pointer to tuples of u32 values (register address, value) for mux
* registers. Expected length of buffer is (2 * sizeof(u32) *
* &n_mux_regs).
*/
__u64 mux_regs_ptr;
/**
* @boolean_regs_ptr:
*
* Pointer to tuples of u32 values (register address, value) for mux
* registers. Expected length of buffer is (2 * sizeof(u32) *
* &n_boolean_regs).
*/
__u64 boolean_regs_ptr;
/**
* @flex_regs_ptr:
*
* Pointer to tuples of u32 values (register address, value) for mux
* registers. Expected length of buffer is (2 * sizeof(u32) *
* &n_flex_regs).
*/
__u64 flex_regs_ptr;
};
/**
* struct drm_i915_query_item - An individual query for the kernel to process.
*
* The behaviour is determined by the @query_id. Note that exactly what
* @data_ptr is also depends on the specific @query_id.
*/
struct drm_i915_query_item {
/**
* @query_id:
*
* The id for this query. Currently accepted query IDs are:
* - %DRM_I915_QUERY_TOPOLOGY_INFO (see struct drm_i915_query_topology_info)
* - %DRM_I915_QUERY_ENGINE_INFO (see struct drm_i915_engine_info)
* - %DRM_I915_QUERY_PERF_CONFIG (see struct drm_i915_query_perf_config)
* - %DRM_I915_QUERY_MEMORY_REGIONS (see struct drm_i915_query_memory_regions)
* - %DRM_I915_QUERY_HWCONFIG_BLOB (see `GuC HWCONFIG blob uAPI`)
* - %DRM_I915_QUERY_GEOMETRY_SUBSLICES (see struct drm_i915_query_topology_info)
* - %DRM_I915_QUERY_GUC_SUBMISSION_VERSION (see struct drm_i915_query_guc_submission_version)
*/
__u64 query_id;
#define DRM_I915_QUERY_TOPOLOGY_INFO 1
#define DRM_I915_QUERY_ENGINE_INFO 2
#define DRM_I915_QUERY_PERF_CONFIG 3
#define DRM_I915_QUERY_MEMORY_REGIONS 4
#define DRM_I915_QUERY_HWCONFIG_BLOB 5
#define DRM_I915_QUERY_GEOMETRY_SUBSLICES 6
#define DRM_I915_QUERY_GUC_SUBMISSION_VERSION 7
/* Must be kept compact -- no holes and well documented */
/**
* @length:
*
* When set to zero by userspace, this is filled with the size of the
* data to be written at the @data_ptr pointer. The kernel sets this
* value to a negative value to signal an error on a particular query
* item.
*/
__s32 length;
/**
* @flags:
*
* When &query_id == %DRM_I915_QUERY_TOPOLOGY_INFO, must be 0.
*
* When &query_id == %DRM_I915_QUERY_PERF_CONFIG, must be one of the
* following:
*
* - %DRM_I915_QUERY_PERF_CONFIG_LIST
* - %DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_UUID
* - %DRM_I915_QUERY_PERF_CONFIG_FOR_UUID
*
* When &query_id == %DRM_I915_QUERY_GEOMETRY_SUBSLICES must contain
* a struct i915_engine_class_instance that references a render engine.
*/
__u32 flags;
#define DRM_I915_QUERY_PERF_CONFIG_LIST 1
#define DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_UUID 2
#define DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_ID 3
/**
* @data_ptr:
*
* Data will be written at the location pointed by @data_ptr when the
* value of @length matches the length of the data to be written by the
* kernel.
*/
__u64 data_ptr;
};
/**
* struct drm_i915_query - Supply an array of struct drm_i915_query_item for the
* kernel to fill out.
*
* Note that this is generally a two step process for each struct
* drm_i915_query_item in the array:
*
* 1. Call the DRM_IOCTL_I915_QUERY, giving it our array of struct
* drm_i915_query_item, with &drm_i915_query_item.length set to zero. The
* kernel will then fill in the size, in bytes, which tells userspace how
* memory it needs to allocate for the blob(say for an array of properties).
*
* 2. Next we call DRM_IOCTL_I915_QUERY again, this time with the
* &drm_i915_query_item.data_ptr equal to our newly allocated blob. Note that
* the &drm_i915_query_item.length should still be the same as what the
* kernel previously set. At this point the kernel can fill in the blob.
*
* Note that for some query items it can make sense for userspace to just pass
* in a buffer/blob equal to or larger than the required size. In this case only
* a single ioctl call is needed. For some smaller query items this can work
* quite well.
*
*/
struct drm_i915_query {
/** @num_items: The number of elements in the @items_ptr array */
__u32 num_items;
/**
* @flags: Unused for now. Must be cleared to zero.
*/
__u32 flags;
/**
* @items_ptr:
*
* Pointer to an array of struct drm_i915_query_item. The number of
* array elements is @num_items.
*/
__u64 items_ptr;
};
/**
* struct drm_i915_query_topology_info
*
* Describes slice/subslice/EU information queried by
* %DRM_I915_QUERY_TOPOLOGY_INFO
*/
struct drm_i915_query_topology_info {
/**
* @flags:
*
* Unused for now. Must be cleared to zero.
*/
__u16 flags;
/**
* @max_slices:
*
* The number of bits used to express the slice mask.
*/
__u16 max_slices;
/**
* @max_subslices:
*
* The number of bits used to express the subslice mask.
*/
__u16 max_subslices;
/**
* @max_eus_per_subslice:
*
* The number of bits in the EU mask that correspond to a single
* subslice's EUs.
*/
__u16 max_eus_per_subslice;
/**
* @subslice_offset:
*
* Offset in data[] at which the subslice masks are stored.
*/
__u16 subslice_offset;
/**
* @subslice_stride:
*
* Stride at which each of the subslice masks for each slice are
* stored.
*/
__u16 subslice_stride;
/**
* @eu_offset:
*
* Offset in data[] at which the EU masks are stored.
*/
__u16 eu_offset;
/**
* @eu_stride:
*
* Stride at which each of the EU masks for each subslice are stored.
*/
__u16 eu_stride;
/**
* @data:
*
* Contains 3 pieces of information :
*
* - The slice mask with one bit per slice telling whether a slice is
* available. The availability of slice X can be queried with the
* following formula :
*
* .. code:: c
*
* (data[X / 8] >> (X % 8)) & 1
*
* Starting with Xe_HP platforms, Intel hardware no longer has
* traditional slices so i915 will always report a single slice
* (hardcoded slicemask = 0x1) which contains all of the platform's
* subslices. I.e., the mask here does not reflect any of the newer
* hardware concepts such as "gslices" or "cslices" since userspace
* is capable of inferring those from the subslice mask.
*
* - The subslice mask for each slice with one bit per subslice telling
* whether a subslice is available. Starting with Gen12 we use the
* term "subslice" to refer to what the hardware documentation
* describes as a "dual-subslices." The availability of subslice Y
* in slice X can be queried with the following formula :
*
* .. code:: c
*
* (data[subslice_offset + X * subslice_stride + Y / 8] >> (Y % 8)) & 1
*
* - The EU mask for each subslice in each slice, with one bit per EU
* telling whether an EU is available. The availability of EU Z in
* subslice Y in slice X can be queried with the following formula :
*
* .. code:: c
*
* (data[eu_offset +
* (X * max_subslices + Y) * eu_stride +
* Z / 8
* ] >> (Z % 8)) & 1
*/
__u8 data[];
};
/**
* DOC: Engine Discovery uAPI
*
* Engine discovery uAPI is a way of enumerating physical engines present in a
* GPU associated with an open i915 DRM file descriptor. This supersedes the old
* way of using `DRM_IOCTL_I915_GETPARAM` and engine identifiers like
* `I915_PARAM_HAS_BLT`.
*
* The need for this interface came starting with Icelake and newer GPUs, which
* started to establish a pattern of having multiple engines of a same class,
* where not all instances were always completely functionally equivalent.
*
* Entry point for this uapi is `DRM_IOCTL_I915_QUERY` with the
* `DRM_I915_QUERY_ENGINE_INFO` as the queried item id.
*
* Example for getting the list of engines:
*
* .. code-block:: C
*
* struct drm_i915_query_engine_info *info;
* struct drm_i915_query_item item = {
* .query_id = DRM_I915_QUERY_ENGINE_INFO;
* };
* struct drm_i915_query query = {
* .num_items = 1,
* .items_ptr = (uintptr_t)&item,
* };
* int err, i;
*
* // First query the size of the blob we need, this needs to be large
* // enough to hold our array of engines. The kernel will fill out the
* // item.length for us, which is the number of bytes we need.
* //
* // Alternatively a large buffer can be allocated straightaway enabling
* // querying in one pass, in which case item.length should contain the
* // length of the provided buffer.
* err = ioctl(fd, DRM_IOCTL_I915_QUERY, &query);
* if (err) ...
*
* info = calloc(1, item.length);
* // Now that we allocated the required number of bytes, we call the ioctl
* // again, this time with the data_ptr pointing to our newly allocated
* // blob, which the kernel can then populate with info on all engines.
* item.data_ptr = (uintptr_t)&info;
*
* err = ioctl(fd, DRM_IOCTL_I915_QUERY, &query);
* if (err) ...
*
* // We can now access each engine in the array
* for (i = 0; i < info->num_engines; i++) {
* struct drm_i915_engine_info einfo = info->engines[i];
* u16 class = einfo.engine.class;
* u16 instance = einfo.engine.instance;
* ....
* }
*
* free(info);
*
* Each of the enumerated engines, apart from being defined by its class and
* instance (see `struct i915_engine_class_instance`), also can have flags and
* capabilities defined as documented in i915_drm.h.
*
* For instance video engines which support HEVC encoding will have the
* `I915_VIDEO_CLASS_CAPABILITY_HEVC` capability bit set.
*
* Engine discovery only fully comes to its own when combined with the new way
* of addressing engines when submitting batch buffers using contexts with
* engine maps configured.
*/
/**
* struct drm_i915_engine_info
*
* Describes one engine and its capabilities as known to the driver.
*/
struct drm_i915_engine_info {
/** @engine: Engine class and instance. */
struct i915_engine_class_instance engine;
/**
* struct drm_i915_query_engine_info
*
* Engine info query enumerates all engines known to the driver by filling in
* an array of struct drm_i915_engine_info structures.
*/
struct drm_i915_query_engine_info {
/** @num_engines: Number of struct drm_i915_engine_info structs following. */
__u32 num_engines;
/**
* struct drm_i915_query_perf_config
*
* Data written by the kernel with query %DRM_I915_QUERY_PERF_CONFIG and
* %DRM_I915_QUERY_GEOMETRY_SUBSLICES.
*/
struct drm_i915_query_perf_config {
union {
/**
* @n_configs:
*
* When &drm_i915_query_item.flags ==
* %DRM_I915_QUERY_PERF_CONFIG_LIST, i915 sets this fields to
* the number of configurations available.
*/
__u64 n_configs;
/**
* @config:
*
* When &drm_i915_query_item.flags ==
* %DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_ID, i915 will use the
* value in this field as configuration identifier to decide
* what data to write into config_ptr.
*/
__u64 config;
/**
* @uuid:
*
* When &drm_i915_query_item.flags ==
* %DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_UUID, i915 will use the
* value in this field as configuration identifier to decide
* what data to write into config_ptr.
*
* String formatted like "%08x-%04x-%04x-%04x-%012x"
*/
char uuid[36];
};
/**
* @flags:
*
* Unused for now. Must be cleared to zero.
*/
__u32 flags;
/**
* @data:
*
* When &drm_i915_query_item.flags == %DRM_I915_QUERY_PERF_CONFIG_LIST,
* i915 will write an array of __u64 of configuration identifiers.
*
* When &drm_i915_query_item.flags == %DRM_I915_QUERY_PERF_CONFIG_DATA,
* i915 will write a struct drm_i915_perf_oa_config. If the following
* fields of struct drm_i915_perf_oa_config are not set to 0, i915 will
* write into the associated pointers the values of submitted when the
* configuration was created :
*
* - &drm_i915_perf_oa_config.n_mux_regs
* - &drm_i915_perf_oa_config.n_boolean_regs
* - &drm_i915_perf_oa_config.n_flex_regs
*/
__u8 data[];
};
/** @memory_instance: Which instance */
__u16 memory_instance;
};
/**
* struct drm_i915_memory_region_info - Describes one region as known to the
* driver.
*
* Note this is using both struct drm_i915_query_item and struct drm_i915_query.
* For this new query we are adding the new query id DRM_I915_QUERY_MEMORY_REGIONS
* at &drm_i915_query_item.query_id.
*/
struct drm_i915_memory_region_info {
/** @region: The class:instance pair encoding */
struct drm_i915_gem_memory_class_instance region;
/** @rsvd0: MBZ */
__u32 rsvd0;
/**
* @probed_size: Memory probed by the driver
*
* Note that it should not be possible to ever encounter a zero value
* here, also note that no current region type will ever return -1 here.
* Although for future region types, this might be a possibility. The
* same applies to the other size fields.
*/
__u64 probed_size;
/**
* @unallocated_size: Estimate of memory remaining
*
* Requires CAP_PERFMON or CAP_SYS_ADMIN to get reliable accounting.
* Without this (or if this is an older kernel) the value here will
* always equal the @probed_size. Note this is only currently tracked
* for I915_MEMORY_CLASS_DEVICE regions (for other types the value here
* will always equal the @probed_size).
*/
__u64 unallocated_size;
union {
/** @rsvd1: MBZ */
__u64 rsvd1[8];
struct {
/**
* @probed_cpu_visible_size: Memory probed by the driver
* that is CPU accessible.
*
* This will be always be <= @probed_size, and the
* remainder (if there is any) will not be CPU
* accessible.
*
* On systems without small BAR, the @probed_size will
* always equal the @probed_cpu_visible_size, since all
* of it will be CPU accessible.
*
* Note this is only tracked for
* I915_MEMORY_CLASS_DEVICE regions (for other types the
* value here will always equal the @probed_size).
*
* Note that if the value returned here is zero, then
* this must be an old kernel which lacks the relevant
* small-bar uAPI support (including
* I915_GEM_CREATE_EXT_FLAG_NEEDS_CPU_ACCESS), but on
* such systems we should never actually end up with a
* small BAR configuration, assuming we are able to load
* the kernel module. Hence it should be safe to treat
* this the same as when @probed_cpu_visible_size ==
* @probed_size.
*/
__u64 probed_cpu_visible_size;
/**
* @unallocated_cpu_visible_size: Estimate of CPU
* visible memory remaining.
*
* Note this is only tracked for
* I915_MEMORY_CLASS_DEVICE regions (for other types the
* value here will always equal the
* @probed_cpu_visible_size).
*
* Requires CAP_PERFMON or CAP_SYS_ADMIN to get reliable
* accounting. Without this the value here will always
* equal the @probed_cpu_visible_size. Note this is only
* currently tracked for I915_MEMORY_CLASS_DEVICE
* regions (for other types the value here will also
* always equal the @probed_cpu_visible_size).
*
* If this is an older kernel the value here will be
* zero, see also @probed_cpu_visible_size.
*/
__u64 unallocated_cpu_visible_size;
};
};
};
/**
* struct drm_i915_query_memory_regions
*
* The region info query enumerates all regions known to the driver by filling
* in an array of struct drm_i915_memory_region_info structures.
*
* Example for getting the list of supported regions:
*
* .. code-block:: C
*
* struct drm_i915_query_memory_regions *info;
* struct drm_i915_query_item item = {
* .query_id = DRM_I915_QUERY_MEMORY_REGIONS;
* };
* struct drm_i915_query query = {
* .num_items = 1,
* .items_ptr = (uintptr_t)&item,
* };
* int err, i;
*
* // First query the size of the blob we need, this needs to be large
* // enough to hold our array of regions. The kernel will fill out the
* // item.length for us, which is the number of bytes we need.
* err = ioctl(fd, DRM_IOCTL_I915_QUERY, &query);
* if (err) ...
*
* info = calloc(1, item.length);
* // Now that we allocated the required number of bytes, we call the ioctl
* // again, this time with the data_ptr pointing to our newly allocated
* // blob, which the kernel can then populate with the all the region info.
* item.data_ptr = (uintptr_t)&info,
*
* err = ioctl(fd, DRM_IOCTL_I915_QUERY, &query);
* if (err) ...
*
* // We can now access each region in the array
* for (i = 0; i < info->num_regions; i++) {
* struct drm_i915_memory_region_info mr = info->regions[i];
* u16 class = mr.region.class;
* u16 instance = mr.region.instance;
*
* ....
* }
*
* free(info);
*/
struct drm_i915_query_memory_regions {
/** @num_regions: Number of supported regions */
__u32 num_regions;
/** @rsvd: MBZ */
__u32 rsvd[3];
/** @regions: Info about each supported region */
struct drm_i915_memory_region_info regions[];
};
/**
* DOC: GuC HWCONFIG blob uAPI
*
* The GuC produces a blob with information about the current device.
* i915 reads this blob from GuC and makes it available via this uAPI.
*
* The format and meaning of the blob content are documented in the
* Programmer's Reference Manual.
*/
/**
* struct drm_i915_gem_create_ext - Existing gem_create behaviour, with added
* extension support using struct i915_user_extension.
*
* Note that new buffer flags should be added here, at least for the stuff that
* is immutable. Previously we would have two ioctls, one to create the object
* with gem_create, and another to apply various parameters, however this
* creates some ambiguity for the params which are considered immutable. Also in
* general we're phasing out the various SET/GET ioctls.
*/
struct drm_i915_gem_create_ext {
/**
* @size: Requested size for the object.
*
* The (page-aligned) allocated size for the object will be returned.
*
* On platforms like DG2/ATS the kernel will always use 64K or larger
* pages for I915_MEMORY_CLASS_DEVICE. The kernel also requires a
* minimum of 64K GTT alignment for such objects.
*
* NOTE: Previously the ABI here required a minimum GTT alignment of 2M
* on DG2/ATS, due to how the hardware implemented 64K GTT page support,
* where we had the following complications:
*
* 1) The entire PDE (which covers a 2MB virtual address range), must
* contain only 64K PTEs, i.e mixing 4K and 64K PTEs in the same
* PDE is forbidden by the hardware.
*
* 2) We still need to support 4K PTEs for I915_MEMORY_CLASS_SYSTEM
* objects.
*
* However on actual production HW this was completely changed to now
* allow setting a TLB hint at the PTE level (see PS64), which is a lot
* more flexible than the above. With this the 2M restriction was
* dropped where we now only require 64K.
*/
__u64 size;
/**
* @handle: Returned handle for the object.
*
* Object handles are nonzero.
*/
__u32 handle;
/**
* @flags: Optional flags.
*
* Supported values:
*
* I915_GEM_CREATE_EXT_FLAG_NEEDS_CPU_ACCESS - Signal to the kernel that
* the object will need to be accessed via the CPU.
*
* Only valid when placing objects in I915_MEMORY_CLASS_DEVICE, and only
* strictly required on configurations where some subset of the device
* memory is directly visible/mappable through the CPU (which we also
* call small BAR), like on some DG2+ systems. Note that this is quite
* undesirable, but due to various factors like the client CPU, BIOS etc
* it's something we can expect to see in the wild. See
* &drm_i915_memory_region_info.probed_cpu_visible_size for how to
* determine if this system applies.
*
* Note that one of the placements MUST be I915_MEMORY_CLASS_SYSTEM, to
* ensure the kernel can always spill the allocation to system memory,
* if the object can't be allocated in the mappable part of
* I915_MEMORY_CLASS_DEVICE.
*
* Also note that since the kernel only supports flat-CCS on objects
* that can *only* be placed in I915_MEMORY_CLASS_DEVICE, we therefore
* don't support I915_GEM_CREATE_EXT_FLAG_NEEDS_CPU_ACCESS together with
* flat-CCS.
*
* Without this hint, the kernel will assume that non-mappable
* I915_MEMORY_CLASS_DEVICE is preferred for this object. Note that the
* kernel can still migrate the object to the mappable part, as a last
* resort, if userspace ever CPU faults this object, but this might be
* expensive, and so ideally should be avoided.
*
* On older kernels which lack the relevant small-bar uAPI support (see
* also &drm_i915_memory_region_info.probed_cpu_visible_size),
* usage of the flag will result in an error, but it should NEVER be
* possible to end up with a small BAR configuration, assuming we can
* also successfully load the i915 kernel module. In such cases the
* entire I915_MEMORY_CLASS_DEVICE region will be CPU accessible, and as
* such there are zero restrictions on where the object can be placed.
*/
#define I915_GEM_CREATE_EXT_FLAG_NEEDS_CPU_ACCESS (1 << 0)
__u32 flags;
/**
* @extensions: The chain of extensions to apply to this object.
*
* This will be useful in the future when we need to support several
* different extensions, and we need to apply more than one when
* creating the object. See struct i915_user_extension.
*
* If we don't supply any extensions then we get the same old gem_create
* behaviour.
*
* For I915_GEM_CREATE_EXT_MEMORY_REGIONS usage see
* struct drm_i915_gem_create_ext_memory_regions.
*
* For I915_GEM_CREATE_EXT_PROTECTED_CONTENT usage see
* struct drm_i915_gem_create_ext_protected_content.
*
* For I915_GEM_CREATE_EXT_SET_PAT usage see
* struct drm_i915_gem_create_ext_set_pat.
*/
#define I915_GEM_CREATE_EXT_MEMORY_REGIONS 0
#define I915_GEM_CREATE_EXT_PROTECTED_CONTENT 1
#define I915_GEM_CREATE_EXT_SET_PAT 2
__u64 extensions;
};
/**
* struct drm_i915_gem_create_ext_memory_regions - The
* I915_GEM_CREATE_EXT_MEMORY_REGIONS extension.
*
* Set the object with the desired set of placements/regions in priority
* order. Each entry must be unique and supported by the device.
*
* This is provided as an array of struct drm_i915_gem_memory_class_instance, or
* an equivalent layout of class:instance pair encodings. See struct
* drm_i915_query_memory_regions and DRM_I915_QUERY_MEMORY_REGIONS for how to
* query the supported regions for a device.
*
* As an example, on discrete devices, if we wish to set the placement as
* device local-memory we can do something like:
*
* .. code-block:: C
*
* struct drm_i915_gem_memory_class_instance region_lmem = {
* .memory_class = I915_MEMORY_CLASS_DEVICE,
* .memory_instance = 0,
* };
* struct drm_i915_gem_create_ext_memory_regions regions = {
* .base = { .name = I915_GEM_CREATE_EXT_MEMORY_REGIONS },
* .regions = (uintptr_t)®ion_lmem,
* .num_regions = 1,
* };
* struct drm_i915_gem_create_ext create_ext = {
* .size = 16 * PAGE_SIZE,
* .extensions = (uintptr_t)®ions,
* };
*
* int err = ioctl(fd, DRM_IOCTL_I915_GEM_CREATE_EXT, &create_ext);
* if (err) ...
*
* At which point we get the object handle in &drm_i915_gem_create_ext.handle,
* along with the final object size in &drm_i915_gem_create_ext.size, which
* should account for any rounding up, if required.
*
* Note that userspace has no means of knowing the current backing region
* for objects where @num_regions is larger than one. The kernel will only
* ensure that the priority order of the @regions array is honoured, either
* when initially placing the object, or when moving memory around due to
* memory pressure
*
* On Flat-CCS capable HW, compression is supported for the objects residing
* in I915_MEMORY_CLASS_DEVICE. When such objects (compressed) have other
* memory class in @regions and migrated (by i915, due to memory
* constraints) to the non I915_MEMORY_CLASS_DEVICE region, then i915 needs to
* decompress the content. But i915 doesn't have the required information to
* decompress the userspace compressed objects.
*
* So i915 supports Flat-CCS, on the objects which can reside only on
* I915_MEMORY_CLASS_DEVICE regions.
*/
struct drm_i915_gem_create_ext_memory_regions {
/** @base: Extension link. See struct i915_user_extension. */
struct i915_user_extension base;
/** @pad: MBZ */
__u32 pad;
/** @num_regions: Number of elements in the @regions array. */
__u32 num_regions;
/**
* @regions: The regions/placements array.
*
* An array of struct drm_i915_gem_memory_class_instance.
*/
__u64 regions;
};
/**
* struct drm_i915_gem_create_ext_protected_content - The
* I915_OBJECT_PARAM_PROTECTED_CONTENT extension.
*
* If this extension is provided, buffer contents are expected to be protected
* by PXP encryption and require decryption for scan out and processing. This
* is only possible on platforms that have PXP enabled, on all other scenarios
* using this extension will cause the ioctl to fail and return -ENODEV. The
* flags parameter is reserved for future expansion and must currently be set
* to zero.
*
* The buffer contents are considered invalid after a PXP session teardown.
*
* The encryption is guaranteed to be processed correctly only if the object
* is submitted with a context created using the
* I915_CONTEXT_PARAM_PROTECTED_CONTENT flag. This will also enable extra checks
* at submission time on the validity of the objects involved.
*
* Below is an example on how to create a protected object:
*
* .. code-block:: C
*
* struct drm_i915_gem_create_ext_protected_content protected_ext = {
* .base = { .name = I915_GEM_CREATE_EXT_PROTECTED_CONTENT },
* .flags = 0,
* };
* struct drm_i915_gem_create_ext create_ext = {
* .size = PAGE_SIZE,
* .extensions = (uintptr_t)&protected_ext,
* };
*
* int err = ioctl(fd, DRM_IOCTL_I915_GEM_CREATE_EXT, &create_ext);
* if (err) ...
*/
struct drm_i915_gem_create_ext_protected_content {
/** @base: Extension link. See struct i915_user_extension. */
struct i915_user_extension base;
/** @flags: reserved for future usage, currently MBZ */
__u32 flags;
};
/**
* struct drm_i915_gem_create_ext_set_pat - The
* I915_GEM_CREATE_EXT_SET_PAT extension.
*
* If this extension is provided, the specified caching policy (PAT index) is
* applied to the buffer object.
*
* Below is an example on how to create an object with specific caching policy:
*
* .. code-block:: C
*
* struct drm_i915_gem_create_ext_set_pat set_pat_ext = {
* .base = { .name = I915_GEM_CREATE_EXT_SET_PAT },
* .pat_index = 0,
* };
* struct drm_i915_gem_create_ext create_ext = {
* .size = PAGE_SIZE,
* .extensions = (uintptr_t)&set_pat_ext,
* };
*
* int err = ioctl(fd, DRM_IOCTL_I915_GEM_CREATE_EXT, &create_ext);
* if (err) ...
*/
struct drm_i915_gem_create_ext_set_pat {
/** @base: Extension link. See struct i915_user_extension. */
struct i915_user_extension base;
/**
* @pat_index: PAT index to be set
* PAT index is a bit field in Page Table Entry to control caching
* behaviors for GPU accesses. The definition of PAT index is
* platform dependent and can be found in hardware specifications,
*/
__u32 pat_index;
/** @rsvd: reserved for future use */
__u32 rsvd;
};
/* ID of the protected content session managed by i915 when PXP is active */
#define I915_PROTECTED_CONTENT_DEFAULT_SESSION 0xf
#if defined(__cplusplus)
}
#endif
#endif /* _UAPI_I915_DRM_H_ */
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.401Bemerkung:
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.