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 "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
47 struct opregion_header
{
61 struct bdb_data_header
{
63 u16 size
; /* data size */
66 struct efp_child_device_config
{
71 u8 dp_onboard_redriver
; /* 158 */
72 u8 dp_ondock_redriver
; /* 158 */
73 u8 hdmi_level_shifter_value
:4; /* 169 */
74 u8 hdmi_max_data_rate
:4; /* 204 */
75 u16 dtd_buf_ptr
; /* 161 */
76 u8 edidless_efp
:1; /* 161 */
77 u8 compression_enable
:1; /* 198 */
78 u8 compression_method
:1; /* 198 */
79 u8 ganged_edp
:1; /* 202 */
81 u8 compression_structure_index
:4; /* 198 */
83 u8 slave_port
; /* 202 */
86 u8 i2c_pin
; /* for add-in card */
87 u8 slave_addr
; /* for add-in card */
91 u8 efp_docked_port
:1; /* 158 */
92 u8 lane_reversal
:1; /* 184 */
93 u8 onboard_lspcon
:1; /* 192 */
94 u8 iboost_enable
:1; /* 196 */
95 u8 hpd_invert
:1; /* BXT 196 */
104 u8 sdvo_stall
:1; /* 158 */
106 u8 integrated_encoder
:1;
109 u8 mipi_bridge_type
; /* 171 */
110 u16 device_class_ext
;
112 u8 dp_usb_type_c
:1; /* 195 */
114 u8 dp_usb_type_c_2x_gpio_index
; /* 195 */
115 u16 dp_usb_type_c_2x_gpio_pin
; /* 195 */
116 u8 iboost_dp
:4; /* 196 */
117 u8 iboost_hdmi
:4; /* 196 */
121 /* header->bdb_offset point to bdb_header offset */
122 struct vbt_header header
;
123 struct bdb_header bdb_header
;
125 struct bdb_data_header general_features_header
;
126 struct bdb_general_features general_features
;
128 struct bdb_data_header general_definitions_header
;
129 struct bdb_general_definitions general_definitions
;
131 struct efp_child_device_config child0
;
132 struct efp_child_device_config child1
;
133 struct efp_child_device_config child2
;
134 struct efp_child_device_config child3
;
136 struct bdb_data_header driver_features_header
;
137 struct bdb_driver_features driver_features
;
140 static void virt_vbt_generation(struct vbt
*v
)
144 memset(v
, 0, sizeof(struct vbt
));
146 v
->header
.signature
[0] = '$';
147 v
->header
.signature
[1] = 'V';
148 v
->header
.signature
[2] = 'B';
149 v
->header
.signature
[3] = 'T';
151 /* there's features depending on version! */
152 v
->header
.version
= 155;
153 v
->header
.header_size
= sizeof(v
->header
);
154 v
->header
.vbt_size
= sizeof(struct vbt
) - sizeof(v
->header
);
155 v
->header
.bdb_offset
= offsetof(struct vbt
, bdb_header
);
157 strcpy(&v
->bdb_header
.signature
[0], "BIOS_DATA_BLOCK");
158 v
->bdb_header
.version
= 186; /* child_dev_size = 38 */
159 v
->bdb_header
.header_size
= sizeof(v
->bdb_header
);
161 v
->bdb_header
.bdb_size
= sizeof(struct vbt
) - sizeof(struct vbt_header
)
162 - sizeof(struct bdb_header
);
164 /* general features */
165 v
->general_features_header
.id
= BDB_GENERAL_FEATURES
;
166 v
->general_features_header
.size
= sizeof(struct bdb_general_features
);
167 v
->general_features
.int_crt_support
= 0;
168 v
->general_features
.int_tv_support
= 0;
171 num_child
= 4; /* each port has one child */
172 v
->general_definitions_header
.id
= BDB_GENERAL_DEFINITIONS
;
173 /* size will include child devices */
174 v
->general_definitions_header
.size
=
175 sizeof(struct bdb_general_definitions
) + num_child
* DEV_SIZE
;
176 v
->general_definitions
.child_dev_size
= DEV_SIZE
;
179 v
->child0
.handle
= DEVICE_TYPE_EFP1
;
180 v
->child0
.device_type
= DEVICE_TYPE_DP
;
181 v
->child0
.dvo_port
= DVO_PORT_DPA
;
182 v
->child0
.aux_channel
= DP_AUX_A
;
183 v
->child0
.dp_compat
= true;
184 v
->child0
.integrated_encoder
= true;
187 v
->child1
.handle
= DEVICE_TYPE_EFP2
;
188 v
->child1
.device_type
= DEVICE_TYPE_DP
;
189 v
->child1
.dvo_port
= DVO_PORT_DPB
;
190 v
->child1
.aux_channel
= DP_AUX_B
;
191 v
->child1
.dp_compat
= true;
192 v
->child1
.integrated_encoder
= true;
195 v
->child2
.handle
= DEVICE_TYPE_EFP3
;
196 v
->child2
.device_type
= DEVICE_TYPE_DP
;
197 v
->child2
.dvo_port
= DVO_PORT_DPC
;
198 v
->child2
.aux_channel
= DP_AUX_C
;
199 v
->child2
.dp_compat
= true;
200 v
->child2
.integrated_encoder
= true;
203 v
->child3
.handle
= DEVICE_TYPE_EFP4
;
204 v
->child3
.device_type
= DEVICE_TYPE_DP
;
205 v
->child3
.dvo_port
= DVO_PORT_DPD
;
206 v
->child3
.aux_channel
= DP_AUX_D
;
207 v
->child3
.dp_compat
= true;
208 v
->child3
.integrated_encoder
= true;
210 /* driver features */
211 v
->driver_features_header
.id
= BDB_DRIVER_FEATURES
;
212 v
->driver_features_header
.size
= sizeof(struct bdb_driver_features
);
213 v
->driver_features
.lvds_config
= BDB_DRIVER_FEATURE_NO_LVDS
;
217 * intel_vgpu_init_opregion - initialize the stuff used to emulate opregion
219 * @gpa: guest physical address of opregion
222 * Zero on success, negative error code if failed.
224 int intel_vgpu_init_opregion(struct intel_vgpu
*vgpu
)
227 struct opregion_header
*header
;
229 const char opregion_signature
[16] = OPREGION_SIGNATURE
;
231 gvt_dbg_core("init vgpu%d opregion\n", vgpu
->id
);
232 vgpu_opregion(vgpu
)->va
= (void *)__get_free_pages(GFP_KERNEL
|
234 get_order(INTEL_GVT_OPREGION_SIZE
));
235 if (!vgpu_opregion(vgpu
)->va
) {
236 gvt_err("fail to get memory for vgpu virt opregion\n");
240 /* emulated opregion with VBT mailbox only */
241 buf
= (u8
*)vgpu_opregion(vgpu
)->va
;
242 header
= (struct opregion_header
*)buf
;
243 memcpy(header
->signature
, opregion_signature
,
244 sizeof(opregion_signature
));
246 header
->opregion_ver
= 0x02000000;
247 header
->mboxes
= MBOX_VBT
;
249 /* for unknown reason, the value in LID field is incorrect
250 * which block the windows guest, so workaround it by force
251 * setting it to "OPEN"
253 buf
[INTEL_GVT_OPREGION_CLID
] = 0x3;
255 /* emulated vbt from virt vbt generation */
256 virt_vbt_generation(&v
);
257 memcpy(buf
+ INTEL_GVT_OPREGION_VBT_OFFSET
, &v
, sizeof(struct vbt
));
262 static int map_vgpu_opregion(struct intel_vgpu
*vgpu
, bool map
)
267 for (i
= 0; i
< INTEL_GVT_OPREGION_PAGES
; i
++) {
268 mfn
= intel_gvt_hypervisor_virt_to_mfn(vgpu_opregion(vgpu
)->va
270 if (mfn
== INTEL_GVT_INVALID_ADDR
) {
271 gvt_vgpu_err("fail to get MFN from VA\n");
274 ret
= intel_gvt_hypervisor_map_gfn_to_mfn(vgpu
,
275 vgpu_opregion(vgpu
)->gfn
[i
],
278 gvt_vgpu_err("fail to map GFN to MFN, errno: %d\n",
284 vgpu_opregion(vgpu
)->mapped
= map
;
290 * intel_vgpu_opregion_base_write_handler - Opregion base register write handler
293 * @gpa: guest physical address of opregion
296 * Zero on success, negative error code if failed.
298 int intel_vgpu_opregion_base_write_handler(struct intel_vgpu
*vgpu
, u32 gpa
)
303 gvt_dbg_core("emulate opregion from kernel\n");
305 switch (intel_gvt_host
.hypervisor_type
) {
306 case INTEL_GVT_HYPERVISOR_KVM
:
307 for (i
= 0; i
< INTEL_GVT_OPREGION_PAGES
; i
++)
308 vgpu_opregion(vgpu
)->gfn
[i
] = (gpa
>> PAGE_SHIFT
) + i
;
310 case INTEL_GVT_HYPERVISOR_XEN
:
312 * Wins guest on Xengt will write this register twice: xen
313 * hvmloader and windows graphic driver.
315 if (vgpu_opregion(vgpu
)->mapped
)
316 map_vgpu_opregion(vgpu
, false);
318 for (i
= 0; i
< INTEL_GVT_OPREGION_PAGES
; i
++)
319 vgpu_opregion(vgpu
)->gfn
[i
] = (gpa
>> PAGE_SHIFT
) + i
;
321 ret
= map_vgpu_opregion(vgpu
, true);
325 gvt_vgpu_err("not supported hypervisor\n");
332 * intel_vgpu_clean_opregion - clean the stuff used to emulate opregion
336 void intel_vgpu_clean_opregion(struct intel_vgpu
*vgpu
)
338 gvt_dbg_core("vgpu%d: clean vgpu opregion\n", vgpu
->id
);
340 if (!vgpu_opregion(vgpu
)->va
)
343 if (intel_gvt_host
.hypervisor_type
== INTEL_GVT_HYPERVISOR_XEN
) {
344 if (vgpu_opregion(vgpu
)->mapped
)
345 map_vgpu_opregion(vgpu
, false);
346 } else if (intel_gvt_host
.hypervisor_type
== INTEL_GVT_HYPERVISOR_KVM
) {
347 /* Guest opregion is released by VFIO */
349 free_pages((unsigned long)vgpu_opregion(vgpu
)->va
,
350 get_order(INTEL_GVT_OPREGION_SIZE
));
352 vgpu_opregion(vgpu
)->va
= NULL
;
357 #define GVT_OPREGION_FUNC(scic) \
360 __ret = (scic & OPREGION_SCIC_FUNC_MASK) >> \
361 OPREGION_SCIC_FUNC_SHIFT; \
365 #define GVT_OPREGION_SUBFUNC(scic) \
368 __ret = (scic & OPREGION_SCIC_SUBFUNC_MASK) >> \
369 OPREGION_SCIC_SUBFUNC_SHIFT; \
373 static const char *opregion_func_name(u32 func
)
375 const char *name
= NULL
;
385 name
= "Get BIOS Data";
389 name
= "System BIOS Callbacks";
399 static const char *opregion_subfunc_name(u32 subfunc
)
401 const char *name
= NULL
;
405 name
= "Supported Calls";
409 name
= "Requested Callbacks";
418 name
= "Boot Display";
422 name
= "TV-Standard/Video-Connector";
426 name
= "Internal Graphics";
430 name
= "Spread Spectrum Clocks";
444 static bool querying_capabilities(u32 scic
)
448 func
= GVT_OPREGION_FUNC(scic
);
449 subfunc
= GVT_OPREGION_SUBFUNC(scic
);
451 if ((func
== INTEL_GVT_OPREGION_SCIC_F_GETBIOSDATA
&&
452 subfunc
== INTEL_GVT_OPREGION_SCIC_SF_SUPPRTEDCALLS
)
453 || (func
== INTEL_GVT_OPREGION_SCIC_F_GETBIOSDATA
&&
454 subfunc
== INTEL_GVT_OPREGION_SCIC_SF_REQEUSTEDCALLBACKS
)
455 || (func
== INTEL_GVT_OPREGION_SCIC_F_GETBIOSCALLBACKS
&&
456 subfunc
== INTEL_GVT_OPREGION_SCIC_SF_SUPPRTEDCALLS
)) {
463 * intel_vgpu_emulate_opregion_request - emulating OpRegion request
465 * @swsci: SWSCI request
468 * Zero on success, negative error code if failed
470 int intel_vgpu_emulate_opregion_request(struct intel_vgpu
*vgpu
, u32 swsci
)
474 u64 scic_pa
= 0, parm_pa
= 0;
477 switch (intel_gvt_host
.hypervisor_type
) {
478 case INTEL_GVT_HYPERVISOR_XEN
:
479 scic
= *((u32
*)vgpu_opregion(vgpu
)->va
+
480 INTEL_GVT_OPREGION_SCIC
);
481 parm
= *((u32
*)vgpu_opregion(vgpu
)->va
+
482 INTEL_GVT_OPREGION_PARM
);
484 case INTEL_GVT_HYPERVISOR_KVM
:
485 scic_pa
= (vgpu_opregion(vgpu
)->gfn
[0] << PAGE_SHIFT
) +
486 INTEL_GVT_OPREGION_SCIC
;
487 parm_pa
= (vgpu_opregion(vgpu
)->gfn
[0] << PAGE_SHIFT
) +
488 INTEL_GVT_OPREGION_PARM
;
490 ret
= intel_gvt_hypervisor_read_gpa(vgpu
, scic_pa
,
491 &scic
, sizeof(scic
));
493 gvt_vgpu_err("guest opregion read error %d, gpa 0x%llx, len %lu\n",
494 ret
, scic_pa
, sizeof(scic
));
498 ret
= intel_gvt_hypervisor_read_gpa(vgpu
, parm_pa
,
499 &parm
, sizeof(parm
));
501 gvt_vgpu_err("guest opregion read error %d, gpa 0x%llx, len %lu\n",
502 ret
, scic_pa
, sizeof(scic
));
508 gvt_vgpu_err("not supported hypervisor\n");
512 if (!(swsci
& SWSCI_SCI_SELECT
)) {
513 gvt_vgpu_err("requesting SMI service\n");
516 /* ignore non 0->1 trasitions */
517 if ((vgpu_cfg_space(vgpu
)[INTEL_GVT_PCI_SWSCI
]
518 & SWSCI_SCI_TRIGGER
) ||
519 !(swsci
& SWSCI_SCI_TRIGGER
)) {
523 func
= GVT_OPREGION_FUNC(scic
);
524 subfunc
= GVT_OPREGION_SUBFUNC(scic
);
525 if (!querying_capabilities(scic
)) {
526 gvt_vgpu_err("requesting runtime service: func \"%s\","
528 opregion_func_name(func
),
529 opregion_subfunc_name(subfunc
));
531 * emulate exit status of function call, '0' means
532 * "failure, generic, unsupported or unknown cause"
534 scic
&= ~OPREGION_SCIC_EXIT_MASK
;
542 switch (intel_gvt_host
.hypervisor_type
) {
543 case INTEL_GVT_HYPERVISOR_XEN
:
544 *((u32
*)vgpu_opregion(vgpu
)->va
+
545 INTEL_GVT_OPREGION_SCIC
) = scic
;
546 *((u32
*)vgpu_opregion(vgpu
)->va
+
547 INTEL_GVT_OPREGION_PARM
) = parm
;
549 case INTEL_GVT_HYPERVISOR_KVM
:
550 ret
= intel_gvt_hypervisor_write_gpa(vgpu
, scic_pa
,
551 &scic
, sizeof(scic
));
553 gvt_vgpu_err("guest opregion write error %d, gpa 0x%llx, len %lu\n",
554 ret
, scic_pa
, sizeof(scic
));
558 ret
= intel_gvt_hypervisor_write_gpa(vgpu
, parm_pa
,
559 &parm
, sizeof(parm
));
561 gvt_vgpu_err("guest opregion write error %d, gpa 0x%llx, len %lu\n",
562 ret
, scic_pa
, sizeof(scic
));
568 gvt_vgpu_err("not supported hypervisor\n");