Skip to content

Commit

Permalink
Enable to (un)hide a PCI device through the API
Browse files Browse the repository at this point in the history
New API:
- `PCI.disable_dom0_access`: hide a PCI device from the dom0 kernel
- `PCI.enable_dom0_access`: unhide a PCI device from the dom0 kernel
- `PCI.is_dom0_access_enabled`: return whether a PCI device is hidden

This is already possible for PGPUs with the `{enable/disable}_dom0_access` calls
this extends it to all PCI devices.

Signed-off-by: Benjamin Reis <[email protected]>
  • Loading branch information
benjamreis committed Mar 22, 2024
1 parent 34dabdf commit 2e48655
Show file tree
Hide file tree
Showing 7 changed files with 201 additions and 3 deletions.
31 changes: 29 additions & 2 deletions ocaml/idl/datamodel.ml
Original file line number Diff line number Diff line change
Expand Up @@ -6519,12 +6519,39 @@ end
(** PCI devices *)

module PCI = struct
let disable_dom0_access =
call ~name:"disable_dom0_access" ~lifecycle:[]
~doc:
"Hide a PCI device from the dom0 kernel. (Takes affect after next \
boot.)"
~params:[(Ref _pci, "self", "The PCI to hide")]
~allowed_roles:_R_POOL_OP ()

let enable_dom0_access =
call ~name:"enable_dom0_access" ~lifecycle:[]
~doc:
"Unhide a PCI device from the dom0 kernel. (Takes affect after next \
boot.)"
~params:[(Ref _pci, "self", "The PCI to unhide")]
~allowed_roles:_R_POOL_OP ()

let is_dom0_access_enabled =
call ~name:"is_dom0_access_enabled" ~lifecycle:[]
~doc:
"Returns whether the PCI device is accessible from the dom0 kernel on \
boot."
~params:[(Ref _pci, "self", "The PCI")]
~result:(Bool, "Whether the PCI is accessible from the dom0 kernel")
~allowed_roles:_R_POOL_OP ()

let t =
create_obj ~name:_pci ~descr:"A PCI device" ~doccomments:[]
~gen_constructor_destructor:false ~gen_events:true ~in_db:true
~lifecycle:[(Published, rel_boston, "")]
~messages:[] ~messages_default_allowed_roles:_R_POOL_OP
~persist:PersistEverything ~in_oss_since:None ~db_logging:Log_destroy
~messages:
[disable_dom0_access; enable_dom0_access; is_dom0_access_enabled]
~messages_default_allowed_roles:_R_POOL_OP ~persist:PersistEverything
~in_oss_since:None ~db_logging:Log_destroy
~contents:
[
uid _pci ~lifecycle:[(Published, rel_boston, "")]
Expand Down
29 changes: 29 additions & 0 deletions ocaml/xapi-cli-server/cli_frontend.ml
Original file line number Diff line number Diff line change
Expand Up @@ -3680,6 +3680,35 @@ let rec cmdtable_data : (string * cmd_spec) list =
; flags= []
}
)
; ( "pci-enable-dom0-access"
, {
reqd= ["uuid"]
; optn= []
; help= "Enable PCI access to dom0."
; implementation= No_fd Cli_operations.pci_enable_dom0_access
; flags= []
}
)
; ( "pci-disable-dom0-access"
, {
reqd= ["uuid"]
; optn= []
; help= "Disable PCI access to dom0."
; implementation= No_fd Cli_operations.pci_disable_dom0_access
; flags= []
}
)
; ( "pci-is-dom0-access-enabled"
, {
reqd= ["uuid"]
; optn= []
; help=
"Returns whether the PCI device is accessible from the dom0 kernel \
on boot."
; implementation= No_fd Cli_operations.is_dom0_access_enabled
; flags= []
}
)
]

let cmdtable : (string, cmd_spec) Hashtbl.t = Hashtbl.create 50
Expand Down
25 changes: 25 additions & 0 deletions ocaml/xapi-cli-server/cli_operations.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1329,6 +1329,11 @@ let gen_cmds rpc session_id =
]
rpc session_id
)
; Client.PCI.(
mk get_all_records_where get_by_uuid pci_record "pci" []
["uuid"; "vendor-name"; "device-name"; "pci-id"]
rpc session_id
)
]

let message_create (_ : printer) rpc session_id params =
Expand Down Expand Up @@ -7473,6 +7478,26 @@ let lvhd_enable_thin_provisioning _printer rpc session_id params =
["sr-uuid"; "initial-allocation"; "allocation-quantum"]
)

let pci_enable_dom0_access _printer rpc session_id params =
let uuid = List.assoc "uuid" params in
let ref = Client.PCI.get_by_uuid ~rpc ~session_id ~uuid in
Client.PCI.enable_dom0_access ~rpc ~session_id ~self:ref

let pci_disable_dom0_access _printer rpc session_id params =
let uuid = List.assoc "uuid" params in
let ref = Client.PCI.get_by_uuid ~rpc ~session_id ~uuid in
Client.PCI.disable_dom0_access ~rpc ~session_id ~self:ref

let is_dom0_access_enabled printer rpc session_id params =
let uuid = List.assoc "uuid" params in
let ref = Client.PCI.get_by_uuid ~rpc ~session_id ~uuid in
printer
(Cli_printer.PMsg
(Bool.to_string
(Client.PCI.is_dom0_access_enabled ~rpc ~session_id ~self:ref)
)
)

module PVS_site = struct
let introduce printer rpc session_id params =
let name_label = List.assoc "name-label" params in
Expand Down
77 changes: 77 additions & 0 deletions ocaml/xapi-cli-server/records.ml
Original file line number Diff line number Diff line change
Expand Up @@ -5500,3 +5500,80 @@ let observer_record rpc session_id observer =
()
]
}

let pci_record rpc session_id pci =
let _ref = ref pci in
let empty_record =
ToGet (fun () -> Client.PCI.get_record ~rpc ~session_id ~self:!_ref)
in
let record = ref empty_record in
let x () = lzy_get record in
let pci_record p =
ref (ToGet (fun () -> Client.PCI.get_record ~rpc ~session_id ~self:p))
in
let xp0 p = lzy_get (pci_record p) in
{
setref=
(fun r ->
_ref := r ;
record := empty_record
)
; setrefrec=
(fun (a, b) ->
_ref := a ;
record := Got b
)
; record= x
; getref= (fun () -> !_ref)
; fields=
[
make_field ~name:"uuid" ~get:(fun () -> (x ()).API.pCI_uuid) ()
; make_field ~name:"vendor-name"
~get:(fun () -> try (x ()).API.pCI_vendor_name with _ -> nid)
()
; make_field ~name:"device-name"
~get:(fun () -> try (x ()).API.pCI_device_name with _ -> nid)
()
; make_field ~name:"driver-name"
~get:(fun () -> try (x ()).API.pCI_driver_name with _ -> nid)
()
; make_field ~name:"host-uuid"
~get:(fun () ->
try get_uuid_from_ref (x ()).API.pCI_host with _ -> nid
)
()
; make_field ~name:"host-name-label"
~get:(fun () ->
try get_name_from_ref (x ()).API.pCI_host with _ -> nid
)
()
; make_field ~name:"pci-id"
~get:(fun () -> try (x ()).API.pCI_pci_id with _ -> nid)
()
; make_field ~name:"dependencies"
~get:(fun () ->
map_and_concat
(fun pci -> (xp0 pci).API.pCI_pci_id)
(x ()).API.pCI_dependencies
)
~get_set:(fun () ->
List.map
(fun pci -> (xp0 pci).API.pCI_pci_id)
(x ()).API.pCI_dependencies
)
()
; make_field ~name:"other-config"
~get:(fun () ->
Record_util.s2sm_to_string "; " (x ()).API.pCI_other_config
)
~add_to_map:(fun key value ->
Client.PCI.add_to_other_config ~rpc ~session_id ~self:pci ~key
~value
)
~remove_from_map:(fun key ->
Client.PCI.remove_from_other_config ~rpc ~session_id ~self:pci ~key
)
~get_map:(fun () -> (x ()).API.pCI_other_config)
()
]
}
26 changes: 25 additions & 1 deletion ocaml/xapi/message_forwarding.ml
Original file line number Diff line number Diff line change
Expand Up @@ -5867,7 +5867,31 @@ functor

module Secret = Local.Secret

module PCI = struct end
module PCI = struct
let disable_dom0_access ~__context ~self =
info "PCI.disable_dom0_access: pci = '%s'" (pci_uuid ~__context self) ;
let host = Db.PCI.get_host ~__context ~self in
let local_fn = Local.PCI.disable_dom0_access ~self in
do_op_on ~__context ~local_fn ~host (fun session_id rpc ->
Client.PCI.disable_dom0_access ~rpc ~session_id ~self
)

let enable_dom0_access ~__context ~self =
info "PCI.enable_dom0_access: pci = '%s'" (pci_uuid ~__context self) ;
let host = Db.PCI.get_host ~__context ~self in
let local_fn = Local.PCI.enable_dom0_access ~self in
do_op_on ~__context ~local_fn ~host (fun session_id rpc ->
Client.PCI.enable_dom0_access ~rpc ~session_id ~self
)

let is_dom0_access_enabled ~__context ~self =
info "PCI.is_dom0_access_enabled: pci = '%s'" (pci_uuid ~__context self) ;
let host = Db.PCI.get_host ~__context ~self in
let local_fn = Local.PCI.is_dom0_access_enabled ~self in
do_op_on ~__context ~local_fn ~host (fun session_id rpc ->
Client.PCI.is_dom0_access_enabled ~rpc ~session_id ~self
)
end

module VTPM = struct
let create ~__context ~vM ~is_unique =
Expand Down
7 changes: 7 additions & 0 deletions ocaml/xapi/xapi_pci.ml
Original file line number Diff line number Diff line change
Expand Up @@ -319,3 +319,10 @@ let get_system_display_device () =
)
None items
with _ -> None

let disable_dom0_access ~__context ~self = Pciops.hide_pci ~__context self

let enable_dom0_access ~__context ~self = Pciops.unhide_pci ~__context self

let is_dom0_access_enabled ~__context ~self =
not (Pciops.is_pci_hidden ~__context self)
9 changes: 9 additions & 0 deletions ocaml/xapi/xapi_pci.mli
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,12 @@ val disable_system_display_device : unit -> unit

val dequarantine : __context:Context.t -> Xenops_interface.Pci.address -> unit
(** dequarantine a PCI device. This is idempotent. *)

val disable_dom0_access : __context:Context.t -> self:API.ref_PCI -> unit
(** Hide a PCI device from the dom0 kernel. (Takes affect after next boot.) *)

val enable_dom0_access : __context:Context.t -> self:API.ref_PCI -> unit
(** Unhide a PCI device from the dom0 kernel. (Takes affect after next boot.) *)

val is_dom0_access_enabled : __context:Context.t -> self:API.ref_PCI -> bool
(** Check whether a PCI device will be hidden from the dom0 kernel on boot. *)

0 comments on commit 2e48655

Please sign in to comment.