<commit_before>(*
 * Copyright (C) 2006-2011 Citrix Systems Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation; version 2.1 only. with the special
 * exception on linking described in file LICENSE.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *)
module D=Debug.Make(struct let name="xapi" end)
open D

open Listext
open Threadext

let calculate_max_capacities ~__context ~pCI ~size ~supported_VGPU_types =
	List.map
		(fun vgpu_type ->
			let max_capacity =
				if Xapi_vgpu_type.requires_passthrough ~__context ~self:vgpu_type
				then Db.PCI.get_functions ~__context ~self:pCI
				else Int64.div size (Db.VGPU_type.get_size ~__context ~self:vgpu_type)
			in
			vgpu_type, max_capacity)
		supported_VGPU_types

let create ~__context ~pCI ~gPU_group ~host ~other_config
		~supported_VGPU_types ~size ~dom0_access 
		~is_system_display_device =
	let pgpu = Ref.make () in
	let uuid = Uuid.to_string (Uuid.make_uuid ()) in
	let supported_VGPU_max_capacities =
		calculate_max_capacities ~__context ~pCI ~size ~supported_VGPU_types
	in
	Db.PGPU.create ~__context ~ref:pgpu ~uuid ~pCI
		~gPU_group ~host ~other_config ~size
		~supported_VGPU_max_capacities ~dom0_access
		~is_system_display_device;
	Db.PGPU.set_supported_VGPU_types ~__context
		~self:pgpu ~value:supported_VGPU_types;
	Db.PGPU.set_enabled_VGPU_types ~__context
		~self:pgpu ~value:supported_VGPU_types;
	debug "PGPU ref='%s' created (host = '%s')" (Ref.string_of pgpu) (Ref.string_of host);
	pgpu

let find_or_create_supported_VGPU_types ~__context ~pci
		~is_system_display_device
		~host_display
		~igd_is_whitelisted
		~is_pci_hidden =
	match
		is_system_display_device,
		host_display,
		is_pci_hidden,
		igd_is_whitelisted
	with
	(* If we're not dealing with the system display device, we don't care about
	 * the state of the other fields. *)
	| false, _, _ ,_
	(* If we are dealing with the system display device, then the host display
	 * must be disabled, the device must be hidden from dom0, and the device
	 * must be whitelisted for passthrough. *)
	| true, `disabled, true, true
	| true, `enable_on_reboot, true, true ->
		Xapi_vgpu_type.find_or_create_supported_types ~__context pci
	(* In any other case, we can't do anything with this GPU. *)
	| _, _, _, _ -> []

let update_gpus ~__context ~host =
	let system_display_device = Xapi_pci.get_system_display_device () in
	let existing_pgpus = List.filter (fun (rf, rc) -> rc.API.pGPU_host = host) (Db.PGPU.get_all_records ~__context) in
	let pcis =
		List.filter (fun self ->
			let class_id = Db.PCI.get_class_id ~__context ~self in
			Db.PCI.get_host ~__context ~self = host
			&& Xapi_pci.(is_class_of_kind Display_controller (int_of_id class_id))
		) (Db.PCI.get_all ~__context) in
	let host_display = Db.Host.get_display ~__context ~self:host in
	let rec find_or_create cur = function
		| [] -> cur
		| pci :: remaining_pcis ->
			let pci_addr =  Some (Db.PCI.get_pci_id ~__context ~self:pci) in
			let is_system_display_device = (system_display_device = pci_addr) in
			let igd_is_whitelisted =
				Xapi_pci_helpers.igd_is_whitelisted ~__context pci
			in
			let pgpu =
				try
					let (rf, rc) = List.find (fun (_, rc) -> rc.API.pGPU_PCI = pci) existing_pgpus in
					(* Determine whether dom0 can access the GPU. On boot, we determine
					 * this from the boot config and put the result in the database.
					 * Otherwise, we determine this from the database. *)
					let is_pci_hidden_ref = ref false in
					if !Xapi_globs.on_system_boot
					then begin
						let is_pci_hidden = Pciops.is_pci_hidden ~__context pci in
						is_pci_hidden_ref := is_pci_hidden;
						let dom0_access =
							if is_pci_hidden
							then `disabled
							else `enabled
						in
						Db.PGPU.set_dom0_access ~__context ~self:rf ~value:dom0_access
					end else begin
						let is_pci_hidden =
							match Db.PGPU.get_dom0_access ~__context ~self:rf with
							| `disabled | `enable_on_reboot -> true
							| _ -> false
						in
						is_pci_hidden_ref := is_pci_hidden
					end;
					let is_pci_hidden = !is_pci_hidden_ref in
					(* Now we've determined whether the PCI is hidden, we can work out the
					 * list of supported VGPU types. *)
					let supported_VGPU_types =
						find_or_create_supported_VGPU_types ~__context ~pci
							~is_system_display_device
							~host_display
							~igd_is_whitelisted
							~is_pci_hidden
					in
					let old_supported_VGPU_types =
						Db.PGPU.get_supported_VGPU_types ~__context ~self:rf in
					let old_enabled_VGPU_types =
						Db.PGPU.get_enabled_VGPU_types ~__context ~self:rf in
					(* Pick up any new supported vGPU configs on the host *)
					Db.PGPU.set_supported_VGPU_types ~__context ~self:rf ~value:supported_VGPU_types;
					(* Calculate the maximum capacities of the supported types. *)
					let max_capacities =
						calculate_max_capacities
							~__context
							~pCI:pci
							~size:(Db.PGPU.get_size ~__context ~self:rf)
							~supported_VGPU_types<commit_msg>CP-12398: Pull a chunk of Xapi_pgpu.update_pgpus into a separate function<commit_after>(*
 * Copyright (C) 2006-2011 Citrix Systems Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation; version 2.1 only. with the special
 * exception on linking described in file LICENSE.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *)
module D=Debug.Make(struct let name="xapi" end)
open D

open Listext
open Threadext

let calculate_max_capacities ~__context ~pCI ~size ~supported_VGPU_types =
	List.map
		(fun vgpu_type ->
			let max_capacity =
				if Xapi_vgpu_type.requires_passthrough ~__context ~self:vgpu_type
				then Db.PCI.get_functions ~__context ~self:pCI
				else Int64.div size (Db.VGPU_type.get_size ~__context ~self:vgpu_type)
			in
			vgpu_type, max_capacity)
		supported_VGPU_types

let create ~__context ~pCI ~gPU_group ~host ~other_config
		~supported_VGPU_types ~size ~dom0_access 
		~is_system_display_device =
	let pgpu = Ref.make () in
	let uuid = Uuid.to_string (Uuid.make_uuid ()) in
	let supported_VGPU_max_capacities =
		calculate_max_capacities ~__context ~pCI ~size ~supported_VGPU_types
	in
	Db.PGPU.create ~__context ~ref:pgpu ~uuid ~pCI
		~gPU_group ~host ~other_config ~size
		~supported_VGPU_max_capacities ~dom0_access
		~is_system_display_device;
	Db.PGPU.set_supported_VGPU_types ~__context
		~self:pgpu ~value:supported_VGPU_types;
	Db.PGPU.set_enabled_VGPU_types ~__context
		~self:pgpu ~value:supported_VGPU_types;
	debug "PGPU ref='%s' created (host = '%s')" (Ref.string_of pgpu) (Ref.string_of host);
	pgpu

let find_or_create_supported_VGPU_types ~__context ~pci
		~is_system_display_device
		~host_display
		~igd_is_whitelisted
		~is_pci_hidden =
	match
		is_system_display_device,
		host_display,
		is_pci_hidden,
		igd_is_whitelisted
	with
	(* If we're not dealing with the system display device, we don't care about
	 * the state of the other fields. *)
	| false, _, _ ,_
	(* If we are dealing with the system display device, then the host display
	 * must be disabled, the device must be hidden from dom0, and the device
	 * must be whitelisted for passthrough. *)
	| true, `disabled, true, true
	| true, `enable_on_reboot, true, true ->
		Xapi_vgpu_type.find_or_create_supported_types ~__context pci
	(* In any other case, we can't do anything with this GPU. *)
	| _, _, _, _ -> []

let sync_pci_hidden ~__context ~pgpu ~pci =
	(* Determine whether dom0 can access the GPU. On boot, we determine
	 * this from the boot config and put the result in the database.
	 * Otherwise, we determine this from the database. *)
	if !Xapi_globs.on_system_boot
	then begin
		let is_pci_hidden = Pciops.is_pci_hidden ~__context pci in
		let dom0_access =
			if is_pci_hidden
			then `disabled
			else `enabled
		in
		Db.PGPU.set_dom0_access ~__context ~self:pgpu ~value:dom0_access;
		is_pci_hidden
	end else begin
		match Db.PGPU.get_dom0_access ~__context ~self:pgpu with
		| `disabled | `enable_on_reboot -> true
		| _ -> false
	end

let update_gpus ~__context ~host =
	let system_display_device = Xapi_pci.get_system_display_device () in
	let existing_pgpus = List.filter (fun (rf, rc) -> rc.API.pGPU_host = host) (Db.PGPU.get_all_records ~__context) in
	let pcis =
		List.filter (fun self ->
			let class_id = Db.PCI.get_class_id ~__context ~self in
			Db.PCI.get_host ~__context ~self = host
			&& Xapi_pci.(is_class_of_kind Display_controller (int_of_id class_id))
		) (Db.PCI.get_all ~__context) in
	let host_display = Db.Host.get_display ~__context ~self:host in
	let rec find_or_create cur = function
		| [] -> cur
		| pci :: remaining_pcis ->
			let pci_addr =  Some (Db.PCI.get_pci_id ~__context ~self:pci) in
			let is_system_display_device = (system_display_device = pci_addr) in
			let igd_is_whitelisted =
				Xapi_pci_helpers.igd_is_whitelisted ~__context pci
			in
			let pgpu =
				try
					let (rf, rc) = List.find (fun (_, rc) -> rc.API.pGPU_PCI = pci) existing_pgpus in
					let is_pci_hidden = sync_pci_hidden ~__context ~pgpu:rf ~pci in
					(* Now we've determined whether the PCI is hidden, we can work out the
					 * list of supported VGPU types. *)
					let supported_VGPU_types =
						find_or_create_supported_VGPU_types ~__context ~pci
							~is_system_display_device
							~host_display
							~igd_is_whitelisted
							~is_pci_hidden
					in
					let old_supported_VGPU_types =
						Db.PGPU.get_supported_VGPU_types ~__context ~self:rf in
					let old_enabled_VGPU_types =
						Db.PGPU.get_enabled_VGPU_types ~__context ~self:rf in
					(* Pick up any new supported vGPU configs on the host *)
					Db.PGPU.set_supported_VGPU_types ~__context ~self:rf ~value:supported_VGPU_types;
					(* Calculate the maximum capacities of the supported types. *)
					let max_capacities =
						calculate_max_capacities
							~__context
							~pCI:pci
							~size:(Db.PGPU.get_size ~__context ~self:rf)
							~supported_VGPU_types
{'fraction_non_alphanumeric': 0.07881259484066767, 'fraction_numerical': 0.00426783004552352, 'mean_word_length': 3.911504424778761, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5181480', 'n_tokens_mistral': 4104, 'n_tokens_neox': 3597, 'n_words': 1031}