2 * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 #include <linux/acpi.h>
29 * Note: Only for GVT-g virtual VBT generation, other usage must
32 #define _INTEL_BIOS_PRIVATE
33 #include "display/intel_vbt_defs.h"
35 #define OPREGION_SIGNATURE "IntelGraphicsMem"
36 #define MBOX_VBT (1<<3)
39 #define DEVICE_TYPE_CRT 0x01
40 #define DEVICE_TYPE_EFP1 0x04
41 #define DEVICE_TYPE_EFP2 0x40
42 #define DEVICE_TYPE_EFP3 0x20
43 #define DEVICE_TYPE_EFP4 0x10
45 struct opregion_header
{
59 struct bdb_data_header
{
61 u16 size
; /* data size */
64 /* For supporting windows guest with opregion, here hardcode the emulated
65 * bdb header version as '186', and the corresponding child_device_config
66 * length should be '33' but not '38'.
68 struct efp_child_device_config
{
73 u8 dp_onboard_redriver
; /* 158 */
74 u8 dp_ondock_redriver
; /* 158 */
75 u8 hdmi_level_shifter_value
:4; /* 169 */
76 u8 hdmi_max_data_rate
:4; /* 204 */
77 u16 dtd_buf_ptr
; /* 161 */
78 u8 edidless_efp
:1; /* 161 */
79 u8 compression_enable
:1; /* 198 */
80 u8 compression_method
:1; /* 198 */
81 u8 ganged_edp
:1; /* 202 */
83 u8 compression_structure_index
:4; /* 198 */
85 u8 slave_port
; /* 202 */
88 u8 i2c_pin
; /* for add-in card */
89 u8 slave_addr
; /* for add-in card */
93 u8 efp_docked_port
:1; /* 158 */
94 u8 lane_reversal
:1; /* 184 */
95 u8 onboard_lspcon
:1; /* 192 */
96 u8 iboost_enable
:1; /* 196 */
97 u8 hpd_invert
:1; /* BXT 196 */
106 u8 sdvo_stall
:1; /* 158 */
108 u8 integrated_encoder
:1;
111 u8 mipi_bridge_type
; /* 171 */
112 u16 device_class_ext
;
117 /* header->bdb_offset point to bdb_header offset */
118 struct vbt_header header
;
119 struct bdb_header bdb_header
;
121 struct bdb_data_header general_features_header
;
122 struct bdb_general_features general_features
;
124 struct bdb_data_header general_definitions_header
;
125 struct bdb_general_definitions general_definitions
;
127 struct efp_child_device_config child0
;
128 struct efp_child_device_config child1
;
129 struct efp_child_device_config child2
;
130 struct efp_child_device_config child3
;
132 struct bdb_data_header driver_features_header
;
133 struct bdb_driver_features driver_features
;
136 static void virt_vbt_generation(struct vbt
*v
)
140 memset(v
, 0, sizeof(struct vbt
));
142 v
->header
.signature
[0] = '$';
143 v
->header
.signature
[1] = 'V';
144 v
->header
.signature
[2] = 'B';
145 v
->header
.signature
[3] = 'T';
147 /* there's features depending on version! */
148 v
->header
.version
= 155;
149 v
->header
.header_size
= sizeof(v
->header
);
150 v
->header
.vbt_size
= sizeof(struct vbt
);
151 v
->header
.bdb_offset
= offsetof(struct vbt
, bdb_header
);
153 strcpy(&v
->bdb_header
.signature
[0], "BIOS_DATA_BLOCK");
154 v
->bdb_header
.version
= 186; /* child_dev_size = 33 */
155 v
->bdb_header
.header_size
= sizeof(v
->bdb_header
);
157 v
->bdb_header
.bdb_size
= sizeof(struct vbt
) - sizeof(struct vbt_header
);
159 /* general features */
160 v
->general_features_header
.id
= BDB_GENERAL_FEATURES
;
161 v
->general_features_header
.size
= sizeof(struct bdb_general_features
);
162 v
->general_features
.int_crt_support
= 0;
163 v
->general_features
.int_tv_support
= 0;
166 num_child
= 4; /* each port has one child */
167 v
->general_definitions
.child_dev_size
=
168 sizeof(struct efp_child_device_config
);
169 v
->general_definitions_header
.id
= BDB_GENERAL_DEFINITIONS
;
170 /* size will include child devices */
171 v
->general_definitions_header
.size
=
172 sizeof(struct bdb_general_definitions
) +
173 num_child
* v
->general_definitions
.child_dev_size
;
176 v
->child0
.handle
= DEVICE_TYPE_EFP1
;
177 v
->child0
.device_type
= DEVICE_TYPE_DP
;
178 v
->child0
.dvo_port
= DVO_PORT_DPA
;
179 v
->child0
.aux_channel
= DP_AUX_A
;
180 v
->child0
.dp_compat
= true;
181 v
->child0
.integrated_encoder
= true;
184 v
->child1
.handle
= DEVICE_TYPE_EFP2
;
185 v
->child1
.device_type
= DEVICE_TYPE_DP
;
186 v
->child1
.dvo_port
= DVO_PORT_DPB
;
187 v
->child1
.aux_channel
= DP_AUX_B
;
188 v
->child1
.dp_compat
= true;
189 v
->child1
.integrated_encoder
= true;
192 v
->child2
.handle
= DEVICE_TYPE_EFP3
;
193 v
->child2
.device_type
= DEVICE_TYPE_DP
;
194 v
->child2
.dvo_port
= DVO_PORT_DPC
;
195 v
->child2
.aux_channel
= DP_AUX_C
;
196 v
->child2
.dp_compat
= true;
197 v
->child2
.integrated_encoder
= true;
200 v
->child3
.handle
= DEVICE_TYPE_EFP4
;
201 v
->child3
.device_type
= DEVICE_TYPE_DP
;
202 v
->child3
.dvo_port
= DVO_PORT_DPD
;
203 v
->child3
.aux_channel
= DP_AUX_D
;
204 v
->child3
.dp_compat
= true;
205 v
->child3
.integrated_encoder
= true;
207 /* driver features */
208 v
->driver_features_header
.id
= BDB_DRIVER_FEATURES
;
209 v
->driver_features_header
.size
= sizeof(struct bdb_driver_features
);
210 v
->driver_features
.lvds_config
= BDB_DRIVER_FEATURE_NO_LVDS
;
214 * intel_vgpu_init_opregion - initialize the stuff used to emulate opregion
218 * Zero on success, negative error code if failed.
220 int intel_vgpu_init_opregion(struct intel_vgpu
*vgpu
)
223 struct opregion_header
*header
;
225 const char opregion_signature
[16] = OPREGION_SIGNATURE
;
227 gvt_dbg_core("init vgpu%d opregion\n", vgpu
->id
);
228 vgpu_opregion(vgpu
)->va
= (void *)__get_free_pages(GFP_KERNEL
|
230 get_order(INTEL_GVT_OPREGION_SIZE
));
231 if (!vgpu_opregion(vgpu
)->va
) {
232 gvt_err("fail to get memory for vgpu virt opregion\n");
236 /* emulated opregion with VBT mailbox only */
237 buf
= (u8
*)vgpu_opregion(vgpu
)->va
;
238 header
= (struct opregion_header
*)buf
;
239 memcpy(header
->signature
, opregion_signature
,
240 sizeof(opregion_signature
));
242 header
->opregion_ver
= 0x02000000;
243 header
->mboxes
= MBOX_VBT
;
245 /* for unknown reason, the value in LID field is incorrect
246 * which block the windows guest, so workaround it by force
247 * setting it to "OPEN"
249 buf
[INTEL_GVT_OPREGION_CLID
] = 0x3;
251 /* emulated vbt from virt vbt generation */
252 virt_vbt_generation(&v
);
253 memcpy(buf
+ INTEL_GVT_OPREGION_VBT_OFFSET
, &v
, sizeof(struct vbt
));
258 static int map_vgpu_opregion(struct intel_vgpu
*vgpu
, bool map
)
263 for (i
= 0; i
< INTEL_GVT_OPREGION_PAGES
; i
++) {
264 mfn
= intel_gvt_hypervisor_virt_to_mfn(vgpu_opregion(vgpu
)->va
266 if (mfn
== INTEL_GVT_INVALID_ADDR
) {
267 gvt_vgpu_err("fail to get MFN from VA\n");
270 ret
= intel_gvt_hypervisor_map_gfn_to_mfn(vgpu
,
271 vgpu_opregion(vgpu
)->gfn
[i
],
274 gvt_vgpu_err("fail to map GFN to MFN, errno: %d\n",
280 vgpu_opregion(vgpu
)->mapped
= map
;
286 * intel_vgpu_opregion_base_write_handler - Opregion base register write handler
289 * @gpa: guest physical address of opregion
292 * Zero on success, negative error code if failed.
294 int intel_vgpu_opregion_base_write_handler(struct intel_vgpu
*vgpu
, u32 gpa
)
299 gvt_dbg_core("emulate opregion from kernel\n");
301 switch (intel_gvt_host
.hypervisor_type
) {
302 case INTEL_GVT_HYPERVISOR_KVM
:
303 for (i
= 0; i
< INTEL_GVT_OPREGION_PAGES
; i
++)
304 vgpu_opregion(vgpu
)->gfn
[i
] = (gpa
>> PAGE_SHIFT
) + i
;
306 case INTEL_GVT_HYPERVISOR_XEN
:
308 * Wins guest on Xengt will write this register twice: xen
309 * hvmloader and windows graphic driver.
311 if (vgpu_opregion(vgpu
)->mapped
)
312 map_vgpu_opregion(vgpu
, false);
314 for (i
= 0; i
< INTEL_GVT_OPREGION_PAGES
; i
++)
315 vgpu_opregion(vgpu
)->gfn
[i
] = (gpa
>> PAGE_SHIFT
) + i
;
317 ret
= map_vgpu_opregion(vgpu
, true);
321 gvt_vgpu_err("not supported hypervisor\n");
328 * intel_vgpu_clean_opregion - clean the stuff used to emulate opregion
332 void intel_vgpu_clean_opregion(struct intel_vgpu
*vgpu
)
334 gvt_dbg_core("vgpu%d: clean vgpu opregion\n", vgpu
->id
);
336 if (!vgpu_opregion(vgpu
)->va
)
339 if (intel_gvt_host
.hypervisor_type
== INTEL_GVT_HYPERVISOR_XEN
) {
340 if (vgpu_opregion(vgpu
)->mapped
)
341 map_vgpu_opregion(vgpu
, false);
342 } else if (intel_gvt_host
.hypervisor_type
== INTEL_GVT_HYPERVISOR_KVM
) {
343 /* Guest opregion is released by VFIO */
345 free_pages((unsigned long)vgpu_opregion(vgpu
)->va
,
346 get_order(INTEL_GVT_OPREGION_SIZE
));
348 vgpu_opregion(vgpu
)->va
= NULL
;
353 #define GVT_OPREGION_FUNC(scic) \
356 __ret = (scic & OPREGION_SCIC_FUNC_MASK) >> \
357 OPREGION_SCIC_FUNC_SHIFT; \
361 #define GVT_OPREGION_SUBFUNC(scic) \
364 __ret = (scic & OPREGION_SCIC_SUBFUNC_MASK) >> \
365 OPREGION_SCIC_SUBFUNC_SHIFT; \
369 static const char *opregion_func_name(u32 func
)
371 const char *name
= NULL
;
381 name
= "Get BIOS Data";
385 name
= "System BIOS Callbacks";
395 static const char *opregion_subfunc_name(u32 subfunc
)
397 const char *name
= NULL
;
401 name
= "Supported Calls";
405 name
= "Requested Callbacks";
414 name
= "Boot Display";
418 name
= "TV-Standard/Video-Connector";
422 name
= "Internal Graphics";
426 name
= "Spread Spectrum Clocks";
440 static bool querying_capabilities(u32 scic
)
444 func
= GVT_OPREGION_FUNC(scic
);
445 subfunc
= GVT_OPREGION_SUBFUNC(scic
);
447 if ((func
== INTEL_GVT_OPREGION_SCIC_F_GETBIOSDATA
&&
448 subfunc
== INTEL_GVT_OPREGION_SCIC_SF_SUPPRTEDCALLS
)
449 || (func
== INTEL_GVT_OPREGION_SCIC_F_GETBIOSDATA
&&
450 subfunc
== INTEL_GVT_OPREGION_SCIC_SF_REQEUSTEDCALLBACKS
)
451 || (func
== INTEL_GVT_OPREGION_SCIC_F_GETBIOSCALLBACKS
&&
452 subfunc
== INTEL_GVT_OPREGION_SCIC_SF_SUPPRTEDCALLS
)) {
459 * intel_vgpu_emulate_opregion_request - emulating OpRegion request
461 * @swsci: SWSCI request
464 * Zero on success, negative error code if failed
466 int intel_vgpu_emulate_opregion_request(struct intel_vgpu
*vgpu
, u32 swsci
)
470 u64 scic_pa
= 0, parm_pa
= 0;
473 switch (intel_gvt_host
.hypervisor_type
) {
474 case INTEL_GVT_HYPERVISOR_XEN
:
475 scic
= *((u32
*)vgpu_opregion(vgpu
)->va
+
476 INTEL_GVT_OPREGION_SCIC
);
477 parm
= *((u32
*)vgpu_opregion(vgpu
)->va
+
478 INTEL_GVT_OPREGION_PARM
);
480 case INTEL_GVT_HYPERVISOR_KVM
:
481 scic_pa
= (vgpu_opregion(vgpu
)->gfn
[0] << PAGE_SHIFT
) +
482 INTEL_GVT_OPREGION_SCIC
;
483 parm_pa
= (vgpu_opregion(vgpu
)->gfn
[0] << PAGE_SHIFT
) +
484 INTEL_GVT_OPREGION_PARM
;
486 ret
= intel_gvt_hypervisor_read_gpa(vgpu
, scic_pa
,
487 &scic
, sizeof(scic
));
489 gvt_vgpu_err("guest opregion read error %d, gpa 0x%llx, len %lu\n",
490 ret
, scic_pa
, sizeof(scic
));
494 ret
= intel_gvt_hypervisor_read_gpa(vgpu
, parm_pa
,
495 &parm
, sizeof(parm
));
497 gvt_vgpu_err("guest opregion read error %d, gpa 0x%llx, len %lu\n",
498 ret
, scic_pa
, sizeof(scic
));
504 gvt_vgpu_err("not supported hypervisor\n");
508 if (!(swsci
& SWSCI_SCI_SELECT
)) {
509 gvt_vgpu_err("requesting SMI service\n");
512 /* ignore non 0->1 trasitions */
513 if ((vgpu_cfg_space(vgpu
)[INTEL_GVT_PCI_SWSCI
]
514 & SWSCI_SCI_TRIGGER
) ||
515 !(swsci
& SWSCI_SCI_TRIGGER
)) {
519 func
= GVT_OPREGION_FUNC(scic
);
520 subfunc
= GVT_OPREGION_SUBFUNC(scic
);
521 if (!querying_capabilities(scic
)) {
522 gvt_vgpu_err("requesting runtime service: func \"%s\","
524 opregion_func_name(func
),
525 opregion_subfunc_name(subfunc
));
527 * emulate exit status of function call, '0' means
528 * "failure, generic, unsupported or unknown cause"
530 scic
&= ~OPREGION_SCIC_EXIT_MASK
;
538 switch (intel_gvt_host
.hypervisor_type
) {
539 case INTEL_GVT_HYPERVISOR_XEN
:
540 *((u32
*)vgpu_opregion(vgpu
)->va
+
541 INTEL_GVT_OPREGION_SCIC
) = scic
;
542 *((u32
*)vgpu_opregion(vgpu
)->va
+
543 INTEL_GVT_OPREGION_PARM
) = parm
;
545 case INTEL_GVT_HYPERVISOR_KVM
:
546 ret
= intel_gvt_hypervisor_write_gpa(vgpu
, scic_pa
,
547 &scic
, sizeof(scic
));
549 gvt_vgpu_err("guest opregion write error %d, gpa 0x%llx, len %lu\n",
550 ret
, scic_pa
, sizeof(scic
));
554 ret
= intel_gvt_hypervisor_write_gpa(vgpu
, parm_pa
,
555 &parm
, sizeof(parm
));
557 gvt_vgpu_err("guest opregion write error %d, gpa 0x%llx, len %lu\n",
558 ret
, scic_pa
, sizeof(scic
));
564 gvt_vgpu_err("not supported hypervisor\n");