From mboxrd@z Thu Jan 1 00:00:00 1970 From: Vincent Hanquez Subject: [PATCH 02/10] add ocaml XC bindings. Date: Tue, 9 Mar 2010 14:41:07 +0000 Message-ID: <1268145675-10375-3-git-send-email-vincent.hanquez@eu.citrix.com> References: <1268145675-10375-1-git-send-email-vincent.hanquez@eu.citrix.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------1.7.0" Return-path: In-Reply-To: <1268145675-10375-1-git-send-email-vincent.hanquez@eu.citrix.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xensource.com Errors-To: xen-devel-bounces@lists.xensource.com To: xen-devel@lists.xensource.com Cc: Vincent Hanquez List-Id: xen-devel@lists.xenproject.org --------------1.7.0 Content-Type: text/plain; charset="UTF-8"; format=fixed Content-Transfer-Encoding: quoted-printable this include a small and simpler reimplementation of libxc. Signed-off-by: Vincent Hanquez --- tools/ocaml/libs/xc/META.in | 4 + tools/ocaml/libs/xc/Makefile | 28 + tools/ocaml/libs/xc/xc.h | 191 +++++ tools/ocaml/libs/xc/xc.ml | 340 ++++++++ tools/ocaml/libs/xc/xc.mli | 196 +++++ tools/ocaml/libs/xc/xc_cpufeature.h | 116 +++ tools/ocaml/libs/xc/xc_cpuid.h | 285 +++++++ tools/ocaml/libs/xc/xc_e820.h | 20 + tools/ocaml/libs/xc/xc_lib.c | 1502 +++++++++++++++++++++++++++++= ++++++ tools/ocaml/libs/xc/xc_stubs.c | 1170 +++++++++++++++++++++++++++ 10 files changed, 3852 insertions(+), 0 deletions(-) create mode 100644 tools/ocaml/libs/xc/META.in create mode 100644 tools/ocaml/libs/xc/Makefile create mode 100644 tools/ocaml/libs/xc/xc.h create mode 100644 tools/ocaml/libs/xc/xc.ml create mode 100644 tools/ocaml/libs/xc/xc.mli create mode 100644 tools/ocaml/libs/xc/xc_cpufeature.h create mode 100644 tools/ocaml/libs/xc/xc_cpuid.h create mode 100644 tools/ocaml/libs/xc/xc_e820.h create mode 100644 tools/ocaml/libs/xc/xc_lib.c create mode 100644 tools/ocaml/libs/xc/xc_stubs.c --------------1.7.0 Content-Type: text/x-patch; name="0002-add-ocaml-XC-bindings.patch" Content-Disposition: attachment; filename="0002-add-ocaml-XC-bindings.patch" Content-Transfer-Encoding: quoted-printable diff --git a/tools/ocaml/libs/xc/META.in b/tools/ocaml/libs/xc/META.in new file mode 100644 index 0000000..e46d7dd --- /dev/null +++ b/tools/ocaml/libs/xc/META.in @@ -0,0 +1,4 @@ +version =3D "@VERSION@" +description =3D "Xen Control Interface" +archive(byte) =3D "xc.cma" +archive(native) =3D "xc.cmxa" diff --git a/tools/ocaml/libs/xc/Makefile b/tools/ocaml/libs/xc/Makefile new file mode 100644 index 0000000..9e361b5 --- /dev/null +++ b/tools/ocaml/libs/xc/Makefile @@ -0,0 +1,28 @@ +TOPLEVEL=3D../.. +include $(TOPLEVEL)/common.make + +CFLAGS +=3D -I../mmap -I./ +OCAMLINCLUDE +=3D -I ../mmap -I ../uuid + +OBJS =3D xc +INTF =3D xc.cmi +LIBS =3D xc.cma xc.cmxa + +xc_OBJS =3D $(OBJS) +xc_C_OBJS =3D xc_lib xc_stubs + +OCAML_LIBRARY =3D xc + +all: $(INTF) $(LIBS) + +libs: $(LIBS) + +.PHONY: install +install: $(LIBS) META + ocamlfind install -destdir $(DESTDIR)$(shell ocamlfind printconf destdi= r) -ldconf ignore xc META $(INTF) $(LIBS) *.a *.so *.cmx + +.PHONY: uninstall +uninstall: + ocamlfind remove xc + +include $(TOPLEVEL)/Makefile.rules diff --git a/tools/ocaml/libs/xc/xc.h b/tools/ocaml/libs/xc/xc.h new file mode 100644 index 0000000..8ef7009 --- /dev/null +++ b/tools/ocaml/libs/xc/xc.h @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2006-2007 XenSource Ltd. + * Copyright (C) 2008 Citrix Ltd. + * Author Vincent Hanquez + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as publis= hed + * 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. + */ + +#define __XEN_TOOLS__ + +#include +#include +#include +#include +#include +#include +#if XEN_SYSCTL_INTERFACE_VERSION < 4 +#include +#else +#include +#endif +#include +#include +#include +#include +#include "xc_e820.h" + +typedef xen_domctl_getdomaininfo_t xc_domaininfo_t; +typedef xen_domctl_getvcpuinfo_t xc_vcpuinfo_t; +typedef xen_sysctl_physinfo_t xc_physinfo_t; + +struct xc_core_header { + unsigned int xch_magic; + unsigned int xch_nr_vcpus; + unsigned int xch_nr_pages; + unsigned int xch_ctxt_offset; + unsigned int xch_index_offset; + unsigned int xch_pages_offset; +}; + +typedef union { +#if defined(__i386__) || defined(__x86_64__) + vcpu_guest_context_x86_64_t x64; + vcpu_guest_context_x86_32_t x32; +#endif + vcpu_guest_context_t c; +} vcpu_guest_context_any_t; + +char * xc_error_get(void); +void xc_error_clear(void); + +int xc_using_injection(void); + +int xc_interface_open(void); +int xc_interface_close(int handle); + +int xc_domain_create(int handle, unsigned int ssidref, + xen_domain_handle_t dhandle, + unsigned int flags, unsigned int *pdomid); +int xc_domain_pause(int handle, unsigned int domid); +int xc_domain_unpause(int handle, unsigned int domid); +int xc_domain_resume_fast(int handle, unsigned int domid); +int xc_domain_destroy(int handle, unsigned int domid); +int xc_domain_shutdown(int handle, int domid, int reason); + +int xc_vcpu_setaffinity(int handle, unsigned int domid, int vcpu, + uint64_t cpumap); +int xc_vcpu_getaffinity(int handle, unsigned int domid, int vcpu, + uint64_t *cpumap); + +int xc_domain_getinfolist(int handle, unsigned int first_domain, + unsigned int max_domains, xc_domaininfo_t *inf= o); +int xc_domain_getinfo(int handle, unsigned int first_domain, + xc_domaininfo_t *info); + +int xc_domain_setmaxmem(int handle, unsigned int domid, unsigned int max= _memkb); +int xc_domain_set_memmap_limit(int handle, unsigned int domid, + unsigned long map_limitkb); + +int xc_domain_set_time_offset(int handle, unsigned int domid, int time_o= ffset); + +int xc_domain_memory_increase_reservation(int handle, unsigned int domid= , + unsigned long nr_extents, + unsigned int extent_order, + unsigned int address_bits, + xen_pfn_t *extent_start); +int xc_domain_memory_decrease_reservation(int handle, unsigned int domid= , + unsigned long nr_extents, + unsigned int extent_order, + unsigned int address_bits, + xen_pfn_t *extent_start); +int xc_domain_memory_populate_physmap(int handle, unsigned int domid, + unsigned long nr_extents, + unsigned int extent_order, + unsigned int address_bits, + xen_pfn_t *extent_start); +int xc_domain_setvmxassist(int handle, unsigned int domid, int use_vmxas= sist); +int xc_domain_max_vcpus(int handle, unsigned int domid, unsigned int max= ); +int xc_domain_sethandle(int handle, unsigned int domid, + xen_domain_handle_t dhandle); +int xc_vcpu_getinfo(int handle, unsigned int domid, unsigned int vcpu, + xc_vcpuinfo_t *info); +int xc_domain_ioport_permission(int handle, unsigned int domid, + unsigned int first_port, unsigned int nr= _ports, + unsigned int allow_access); +int xc_vcpu_setcontext(int handle, unsigned int domid, + unsigned int vcpu, vcpu_guest_context_any_t *ctxt= ); +int xc_vcpu_getcontext(int handle, unsigned int domid, + unsigned int vcpu, vcpu_guest_context_any_t *ctxt= ); +int xc_domain_irq_permission(int handle, unsigned int domid, + unsigned char pirq, unsigned char allow_acc= ess); +int xc_domain_iomem_permission(int handle, unsigned int domid, + unsigned long first_mfn, unsigned long nr= _mfns, + unsigned char allow_access); +long long xc_domain_get_cpu_usage(int handle, unsigned int domid, + unsigned int vcpu); +void *xc_map_foreign_range(int handle, unsigned int domid, + int size, int prot, unsigned long mfn); +int xc_map_foreign_ranges(int handle, unsigned int domid, + privcmd_mmap_entry_t *entries, int nr); +int xc_readconsolering(int handle, char **pbuffer, + unsigned int *pnr_chars, int clear); +int xc_send_debug_keys(int handle, char *keys); +int xc_physinfo(int handle, xc_physinfo_t *put_info); +int xc_pcpu_info(int handle, int max_cpus, uint64_t *info, int *nr_cpus)= ; +int xc_sched_id(int handle, int *sched_id); +int xc_version(int handle, int cmd, void *arg); +int xc_evtchn_alloc_unbound(int handle, unsigned int domid, + unsigned int remote_domid); +int xc_evtchn_reset(int handle, unsigned int domid); + +int xc_sched_credit_domain_set(int handle, unsigned int domid, + struct xen_domctl_sched_credit *sdom); +int xc_sched_credit_domain_get(int handle, unsigned int domid, + struct xen_domctl_sched_credit *sdom); +int xc_shadow_allocation_get(int handle, unsigned int domid, + uint32_t *mb); +int xc_shadow_allocation_set(int handle, unsigned int domid, + uint32_t mb); +int xc_domain_get_pfn_list(int handle, unsigned int domid, + xen_pfn_t *pfn_array, unsigned long max_pfns)= ; +int xc_hvm_check_pvdriver(int handle, unsigned int domid); + +int xc_domain_assign_device(int handle, unsigned int domid, + int domain, int bus, int slot, int func); +int xc_domain_deassign_device(int handle, unsigned int domid, + int domain, int bus, int slot, int func); +int xc_domain_test_assign_device(int handle, unsigned int domid, + int domain, int bus, int slot, int func= ); +int xc_domain_watchdog(int handle, int id, uint32_t timeout); +int xc_domain_set_machine_address_size(int xc, uint32_t domid, unsigned = int width); +int xc_domain_get_machine_address_size(int xc, uint32_t domid); + +int xc_domain_cpuid_set(int xc, unsigned int domid, int hvm, + uint32_t input, uint32_t oinput, + char *config[4], char *config_out[4]); +int xc_domain_cpuid_apply(int xc, unsigned int domid, int hvm); +int xc_cpuid_check(uint32_t input, uint32_t optsubinput, + char *config[4], char *config_out[4]); + +int xc_domain_send_s3resume(int handle, unsigned int domid); +int xc_domain_set_vpt_align(int handle, unsigned int domid, int vpt_alig= n); +int xc_domain_set_hpet(int handle, unsigned int domid, int hpet); +int xc_domain_set_timer_mode(int handle, unsigned int domid, int mode); +int xc_domain_get_acpi_s_state(int handle, unsigned int domid); + +#if XEN_SYSCTL_INTERFACE_VERSION >=3D 6 +#define SAFEDIV(a, b) (((b) > 0) ? (a) / (b) : (a)) +#define COMPAT_FIELD_physinfo_get_nr_cpus(p) (p).nr_cpus +#define COMPAT_FIELD_physinfo_get_sockets_per_node(p) \ + SAFEDIV((p).nr_cpus, ((p).threads_per_core * (p).cores_per_socket * (p)= .nr_nodes)) +#else +#define COMPAT_FIELD_physinfo_get_nr_cpus(p) \ + ((p).threads_per_core * (p).sockets_per_node * \ + (p).cores_per_socket * (p).threads_per_core) +#define COMPAT_FIELD_physinfo_get_sockets_per_node(p) (p).sockets_per_no= de +#endif + +#if __XEN_LATEST_INTERFACE_VERSION__ >=3D 0x00030209 +#define COMPAT_FIELD_ADDRESS_BITS mem_flags +#else +#define COMPAT_FIELD_ADDRESS_BITS address_bits +#endif diff --git a/tools/ocaml/libs/xc/xc.ml b/tools/ocaml/libs/xc/xc.ml new file mode 100644 index 0000000..b9dd284 --- /dev/null +++ b/tools/ocaml/libs/xc/xc.ml @@ -0,0 +1,340 @@ +(* + * Copyright (C) 2006-2007 XenSource Ltd. + * Copyright (C) 2008 Citrix Ltd. + * Author Vincent Hanquez + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as publis= hed + * 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. + *) + +(** *) +type domid =3D int + +(* ** xenctrl.h ** *) + +type vcpuinfo =3D +{ + online: bool; + blocked: bool; + running: bool; + cputime: int64; + cpumap: int32; +} + +type domaininfo =3D +{ + domid : domid; + dying : bool; + shutdown : bool; + paused : bool; + blocked : bool; + running : bool; + hvm_guest : bool; + shutdown_code : int; + total_memory_pages: nativeint; + max_memory_pages : nativeint; + shared_info_frame : int64; + cpu_time : int64; + nr_online_vcpus : int; + max_vcpu_id : int; + ssidref : int32; + handle : int array; +} + +type sched_control =3D +{ + weight : int; + cap : int; +} + +type physinfo_cap_flag =3D + | CAP_HVM + | CAP_DirectIO + +type physinfo =3D +{ + threads_per_core : int; + cores_per_socket : int; + nr_cpus : int; + max_node_id : int; + cpu_khz : int; + total_pages : nativeint; + free_pages : nativeint; + scrub_pages : nativeint; + (* XXX hw_cap *) + capabilities : physinfo_cap_flag list; +} + +type version =3D +{ + major : int; + minor : int; + extra : string; +} + + +type compile_info =3D +{ + compiler : string; + compile_by : string; + compile_domain : string; + compile_date : string; +} + +type shutdown_reason =3D Poweroff | Reboot | Suspend | Crash | Halt + +type domain_create_flag =3D CDF_HVM | CDF_HAP + +exception Error of string + +type handle + +(* this is only use by coredumping *) +external sizeof_core_header: unit -> int + =3D "stub_sizeof_core_header" +external sizeof_vcpu_guest_context: unit -> int + =3D "stub_sizeof_vcpu_guest_context" +external sizeof_xen_pfn: unit -> int =3D "stub_sizeof_xen_pfn" +(* end of use *) + +external interface_open: unit -> handle =3D "stub_xc_interface_open" +external interface_close: handle -> unit =3D "stub_xc_interface_close" + +external using_injection: unit -> bool =3D "stub_xc_using_injection" + +let with_intf f =3D + let xc =3D interface_open () in + let r =3D try f xc with exn -> interface_close xc; raise exn in + interface_close xc; + r + +external _domain_create: handle -> int32 -> domain_create_flag list -> i= nt array -> domid + =3D "stub_xc_domain_create" + +let domain_create handle n flags uuid =3D + _domain_create handle n flags (Uuid.int_array_of_uuid uuid) + +external _domain_sethandle: handle -> domid -> int array -> unit + =3D "stub_xc_domain_sethandle" + +let domain_sethandle handle n uuid =3D + _domain_sethandle handle n (Uuid.int_array_of_uuid uuid) + +external domain_setvmxassist: handle -> domid -> bool -> unit + =3D "stub_xc_domain_setvmxassist" + +external domain_max_vcpus: handle -> domid -> int -> unit + =3D "stub_xc_domain_max_vcpus" + +external domain_pause: handle -> domid -> unit =3D "stub_xc_domain_pause= " +external domain_unpause: handle -> domid -> unit =3D "stub_xc_domain_unp= ause" +external domain_resume_fast: handle -> domid -> unit =3D "stub_xc_domain= _resume_fast" +external domain_destroy: handle -> domid -> unit =3D "stub_xc_domain_des= troy" + +external domain_shutdown: handle -> domid -> shutdown_reason -> unit + =3D "stub_xc_domain_shutdown" + +external _domain_getinfolist: handle -> domid -> int -> domaininfo list + =3D "stub_xc_domain_getinfolist" + +let domain_getinfolist handle first_domain =3D + let nb =3D 2 in + let last_domid l =3D (List.hd l).domid + 1 in + let rec __getlist from =3D + let l =3D _domain_getinfolist handle from nb in + (if List.length l =3D nb then __getlist (last_domid l) else []) @ l + in + List.rev (__getlist first_domain) + +external domain_getinfo: handle -> domid -> domaininfo=3D "stub_xc_domai= n_getinfo" + +external domain_get_vcpuinfo: handle -> int -> int -> vcpuinfo + =3D "stub_xc_vcpu_getinfo" + +external domain_ioport_permission: handle -> domid -> int -> int -> bool= -> unit + =3D "stub_xc_domain_ioport_permission" +external domain_iomem_permission: handle -> domid -> nativeint -> native= int -> bool -> unit + =3D "stub_xc_domain_iomem_permission" +external domain_irq_permission: handle -> domid -> int -> bool -> unit + =3D "stub_xc_domain_irq_permission" + +external vcpu_affinity_set: handle -> domid -> int -> int64 -> unit + =3D "stub_xc_vcpu_setaffinity" +external vcpu_affinity_get: handle -> domid -> int -> int64 + =3D "stub_xc_vcpu_getaffinity" + +external vcpu_context_get: handle -> domid -> int -> string + =3D "stub_xc_vcpu_context_get" + +external sched_id: handle -> int =3D "stub_xc_sched_id" + +external sched_credit_domain_set: handle -> domid -> sched_control -> un= it + =3D "stub_sched_credit_domain_set" +external sched_credit_domain_get: handle -> domid -> sched_control + =3D "stub_sched_credit_domain_get" + +external shadow_allocation_set: handle -> domid -> int -> unit + =3D "stub_shadow_allocation_set" +external shadow_allocation_get: handle -> domid -> int + =3D "stub_shadow_allocation_get" + +external evtchn_alloc_unbound: handle -> domid -> domid -> int + =3D "stub_xc_evtchn_alloc_unbound" +external evtchn_reset: handle -> domid -> unit =3D "stub_xc_evtchn_reset= " + +external readconsolering: handle -> string =3D "stub_xc_readconsolering" + +external send_debug_keys: handle -> string -> unit =3D "stub_xc_send_deb= ug_keys" +external physinfo: handle -> physinfo =3D "stub_xc_physinfo" +external pcpu_info: handle -> int -> int64 array =3D "stub_xc_pcpu_info" + +external domain_setmaxmem: handle -> domid -> int64 -> unit + =3D "stub_xc_domain_setmaxmem" +external domain_set_memmap_limit: handle -> domid -> int64 -> unit + =3D "stub_xc_domain_set_memmap_limit" +external domain_memory_increase_reservation: handle -> domid -> int64 ->= unit + =3D "stub_xc_domain_memory_increase_reservation" + +external domain_set_machine_address_size: handle -> domid -> int -> unit + =3D "stub_xc_domain_set_machine_address_size" +external domain_get_machine_address_size: handle -> domid -> int + =3D "stub_xc_domain_get_machine_address_size" + +external domain_cpuid_set: handle -> domid -> bool -> (int64 * (int64 op= tion)) + -> string option array + -> string option array + =3D "stub_xc_domain_cpuid_set" +external domain_cpuid_apply: handle -> domid -> bool -> unit + =3D "stub_xc_domain_cpuid_apply" +external cpuid_check: (int64 * (int64 option)) -> string option array ->= (bool * string option array) + =3D "stub_xc_cpuid_check" + +external map_foreign_range: handle -> domid -> int + -> nativeint -> Mmap.mmap_interface + =3D "stub_map_foreign_range" + +external domain_get_pfn_list: handle -> domid -> nativeint -> nativeint = array + =3D "stub_xc_domain_get_pfn_list" + +external domain_assign_device: handle -> domid -> (int * int * int * int= ) -> unit + =3D "stub_xc_domain_assign_device" +external domain_deassign_device: handle -> domid -> (int * int * int * i= nt) -> unit + =3D "stub_xc_domain_deassign_device" +external domain_test_assign_device: handle -> domid -> (int * int * int = * int) -> bool + =3D "stub_xc_domain_test_assign_device" + +external domain_set_timer_mode: handle -> domid -> int -> unit =3D "stub= _xc_domain_set_timer_mode" +external domain_set_hpet: handle -> domid -> int -> unit =3D "stub_xc_do= main_set_hpet" +external domain_set_vpt_align: handle -> domid -> int -> unit =3D "stub_= xc_domain_set_vpt_align" + +external domain_send_s3resume: handle -> domid -> unit =3D "stub_xc_doma= in_send_s3resume" +external domain_get_acpi_s_state: handle -> domid -> int =3D "stub_xc_do= main_get_acpi_s_state" + +(** check if some hvm domain got pv driver or not *) +external hvm_check_pvdriver: handle -> domid -> bool + =3D "stub_xc_hvm_check_pvdriver" + +external version: handle -> version =3D "stub_xc_version_version" +external version_compile_info: handle -> compile_info + =3D "stub_xc_version_compile_info" +external version_changeset: handle -> string =3D "stub_xc_version_change= set" +external version_capabilities: handle -> string =3D + "stub_xc_version_capabilities" + +external watchdog : handle -> int -> int32 -> int + =3D "stub_xc_watchdog" + +(* core dump structure *) +type core_magic =3D Magic_hvm | Magic_pv + +type core_header =3D { + xch_magic: core_magic; + xch_nr_vcpus: int; + xch_nr_pages: nativeint; + xch_index_offset: int64; + xch_ctxt_offset: int64; + xch_pages_offset: int64; +} + +external marshall_core_header: core_header -> string =3D "stub_marshall_= core_header" + +(* coredump *) +let coredump xch domid fd =3D + let dump s =3D + let wd =3D Unix.write fd s 0 (String.length s) in + if wd <> String.length s then + failwith "error while writing"; + in + + let info =3D domain_getinfo xch domid in + + let nrpages =3D info.total_memory_pages in + let ctxt =3D Array.make info.max_vcpu_id None in + let nr_vcpus =3D ref 0 in + for i =3D 0 to info.max_vcpu_id - 1 + do + ctxt.(i) <- try + let v =3D vcpu_context_get xch domid i in + incr nr_vcpus; + Some v + with _ -> None + done; + + (* FIXME page offset if not rounded to sup *) + let page_offset =3D + Int64.add + (Int64.of_int (sizeof_core_header () + + (sizeof_vcpu_guest_context () * !nr_vcpus))) + (Int64.of_nativeint ( + Nativeint.mul + (Nativeint.of_int (sizeof_xen_pfn ())) + nrpages) + ) + in + + let header =3D { + xch_magic =3D if info.hvm_guest then Magic_hvm else Magic_pv; + xch_nr_vcpus =3D !nr_vcpus; + xch_nr_pages =3D nrpages; + xch_ctxt_offset =3D Int64.of_int (sizeof_core_header ()); + xch_index_offset =3D Int64.of_int (sizeof_core_header () + + sizeof_vcpu_guest_context ()); + xch_pages_offset =3D page_offset; + } in + + dump (marshall_core_header header); + for i =3D 0 to info.max_vcpu_id - 1 + do + match ctxt.(i) with + | None -> () + | Some ctxt_i -> dump ctxt_i + done; + let pfns =3D domain_get_pfn_list xch domid nrpages in + if Array.length pfns <> Nativeint.to_int nrpages then + failwith "could not get the page frame list"; + + let page_size =3D Mmap.getpagesize () in + for i =3D 0 to Nativeint.to_int nrpages - 1 + do + let page =3D map_foreign_range xch domid page_size pfns.(i) in + let data =3D Mmap.read page 0 page_size in + Mmap.unmap page; + dump data + done + +(* ** Misc ** *) + +(** + Convert the given number of pages to an amount in KiB, rounded up. + *) +external pages_to_kib : int64 -> int64 =3D "stub_pages_to_kib" +let pages_to_mib pages =3D Int64.div (pages_to_kib pages) 1024L + +let _ =3D Callback.register_exception "xc.error" (Error "register_callba= ck") diff --git a/tools/ocaml/libs/xc/xc.mli b/tools/ocaml/libs/xc/xc.mli new file mode 100644 index 0000000..dc55b67 --- /dev/null +++ b/tools/ocaml/libs/xc/xc.mli @@ -0,0 +1,196 @@ +(* + * Copyright (C) 2006-2007 XenSource Ltd. + * Copyright (C) 2008 Citrix Ltd. + * Author Vincent Hanquez + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as publis= hed + * 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. + *) + +type domid =3D int +type vcpuinfo =3D { + online : bool; + blocked : bool; + running : bool; + cputime : int64; + cpumap : int32; +} +type domaininfo =3D { + domid : domid; + dying : bool; + shutdown : bool; + paused : bool; + blocked : bool; + running : bool; + hvm_guest : bool; + shutdown_code : int; + total_memory_pages : nativeint; + max_memory_pages : nativeint; + shared_info_frame : int64; + cpu_time : int64; + nr_online_vcpus : int; + max_vcpu_id : int; + ssidref : int32; + handle : int array; +} +type sched_control =3D { weight : int; cap : int; } +type physinfo_cap_flag =3D CAP_HVM | CAP_DirectIO +type physinfo =3D { + threads_per_core : int; + cores_per_socket : int; + nr_cpus : int; + max_node_id : int; + cpu_khz : int; + total_pages : nativeint; + free_pages : nativeint; + scrub_pages : nativeint; + capabilities : physinfo_cap_flag list; +} +type version =3D { major : int; minor : int; extra : string; } +type compile_info =3D { + compiler : string; + compile_by : string; + compile_domain : string; + compile_date : string; +} +type shutdown_reason =3D Poweroff | Reboot | Suspend | Crash | Halt + +type domain_create_flag =3D CDF_HVM | CDF_HAP + +exception Error of string +type handle +external sizeof_core_header : unit -> int =3D "stub_sizeof_core_header" +external sizeof_vcpu_guest_context : unit -> int + =3D "stub_sizeof_vcpu_guest_context" +external sizeof_xen_pfn : unit -> int =3D "stub_sizeof_xen_pfn" +external interface_open : unit -> handle =3D "stub_xc_interface_open" +external using_injection : unit -> bool =3D "stub_xc_using_injection" +external interface_close : handle -> unit =3D "stub_xc_interface_close" +val with_intf : (handle -> 'a) -> 'a +external _domain_create : handle -> int32 -> domain_create_flag list -> = int array -> domid + =3D "stub_xc_domain_create" +val domain_create : handle -> int32 -> domain_create_flag list -> 'a Uui= d.t -> domid +external _domain_sethandle : handle -> domid -> int array -> unit + =3D "stub_xc_domain_sethandle" +val domain_sethandle : handle -> domid -> 'a Uuid.t -> unit +external domain_setvmxassist: handle -> domid -> bool -> unit + =3D "stub_xc_domain_setvmxassist" +external domain_max_vcpus : handle -> domid -> int -> unit + =3D "stub_xc_domain_max_vcpus" +external domain_pause : handle -> domid -> unit =3D "stub_xc_domain_paus= e" +external domain_unpause : handle -> domid -> unit =3D "stub_xc_domain_un= pause" +external domain_resume_fast : handle -> domid -> unit + =3D "stub_xc_domain_resume_fast" +external domain_destroy : handle -> domid -> unit =3D "stub_xc_domain_de= stroy" +external domain_shutdown : handle -> domid -> shutdown_reason -> unit + =3D "stub_xc_domain_shutdown" +external _domain_getinfolist : handle -> domid -> int -> domaininfo list + =3D "stub_xc_domain_getinfolist" +val domain_getinfolist : handle -> domid -> domaininfo list +external domain_getinfo : handle -> domid -> domaininfo + =3D "stub_xc_domain_getinfo" +external domain_get_vcpuinfo : handle -> int -> int -> vcpuinfo + =3D "stub_xc_vcpu_getinfo" +external domain_ioport_permission: handle -> domid -> int -> int -> bool= -> unit + =3D "stub_xc_domain_ioport_permission" +external domain_iomem_permission: handle -> domid -> nativeint -> native= int -> bool -> unit + =3D "stub_xc_domain_iomem_permission" +external domain_irq_permission: handle -> domid -> int -> bool -> unit + =3D "stub_xc_domain_irq_permission" +external vcpu_affinity_set : handle -> domid -> int -> int64 -> unit + =3D "stub_xc_vcpu_setaffinity" +external vcpu_affinity_get : handle -> domid -> int -> int64 + =3D "stub_xc_vcpu_getaffinity" +external vcpu_context_get : handle -> domid -> int -> string + =3D "stub_xc_vcpu_context_get" +external sched_id : handle -> int =3D "stub_xc_sched_id" +external sched_credit_domain_set : handle -> domid -> sched_control -> u= nit + =3D "stub_sched_credit_domain_set" +external sched_credit_domain_get : handle -> domid -> sched_control + =3D "stub_sched_credit_domain_get" +external shadow_allocation_set : handle -> domid -> int -> unit + =3D "stub_shadow_allocation_set" +external shadow_allocation_get : handle -> domid -> int + =3D "stub_shadow_allocation_get" +external evtchn_alloc_unbound : handle -> domid -> domid -> int + =3D "stub_xc_evtchn_alloc_unbound" +external evtchn_reset : handle -> domid -> unit =3D "stub_xc_evtchn_rese= t" +external readconsolering : handle -> string =3D "stub_xc_readconsolering= " +external send_debug_keys : handle -> string -> unit =3D "stub_xc_send_de= bug_keys" +external physinfo : handle -> physinfo =3D "stub_xc_physinfo" +external pcpu_info: handle -> int -> int64 array =3D "stub_xc_pcpu_info" +external domain_setmaxmem : handle -> domid -> int64 -> unit + =3D "stub_xc_domain_setmaxmem" +external domain_set_memmap_limit : handle -> domid -> int64 -> unit + =3D "stub_xc_domain_set_memmap_limit" +external domain_memory_increase_reservation : + handle -> domid -> int64 -> unit + =3D "stub_xc_domain_memory_increase_reservation" +external map_foreign_range : + handle -> domid -> int -> nativeint -> Mmap.mmap_interface + =3D "stub_map_foreign_range" +external domain_get_pfn_list : + handle -> domid -> nativeint -> nativeint array + =3D "stub_xc_domain_get_pfn_list" + +external domain_assign_device: handle -> domid -> (int * int * int * int= ) -> unit + =3D "stub_xc_domain_assign_device" +external domain_deassign_device: handle -> domid -> (int * int * int * i= nt) -> unit + =3D "stub_xc_domain_deassign_device" +external domain_test_assign_device: handle -> domid -> (int * int * int = * int) -> bool + =3D "stub_xc_domain_test_assign_device" + +external domain_set_timer_mode: handle -> domid -> int -> unit =3D "stub= _xc_domain_set_timer_mode" +external domain_set_hpet: handle -> domid -> int -> unit =3D "stub_xc_do= main_set_hpet" +external domain_set_vpt_align: handle -> domid -> int -> unit =3D "stub_= xc_domain_set_vpt_align" + +external domain_send_s3resume: handle -> domid -> unit + =3D "stub_xc_domain_send_s3resume" +external domain_get_acpi_s_state: handle -> domid -> int =3D "stub_xc_do= main_get_acpi_s_state" + +external hvm_check_pvdriver : handle -> domid -> bool + =3D "stub_xc_hvm_check_pvdriver" +external version : handle -> version =3D "stub_xc_version_version" +external version_compile_info : handle -> compile_info + =3D "stub_xc_version_compile_info" +external version_changeset : handle -> string =3D "stub_xc_version_chang= eset" +external version_capabilities : handle -> string + =3D "stub_xc_version_capabilities" +type core_magic =3D Magic_hvm | Magic_pv +type core_header =3D { + xch_magic : core_magic; + xch_nr_vcpus : int; + xch_nr_pages : nativeint; + xch_index_offset : int64; + xch_ctxt_offset : int64; + xch_pages_offset : int64; +} +external marshall_core_header : core_header -> string + =3D "stub_marshall_core_header" +val coredump : handle -> domid -> Unix.file_descr -> unit +external pages_to_kib : int64 -> int64 =3D "stub_pages_to_kib" +val pages_to_mib : int64 -> int64 +external watchdog : handle -> int -> int32 -> int + =3D "stub_xc_watchdog" + +external domain_set_machine_address_size: handle -> domid -> int -> unit + =3D "stub_xc_domain_set_machine_address_size" +external domain_get_machine_address_size: handle -> domid -> int + =3D "stub_xc_domain_get_machine_address_size" + +external domain_cpuid_set: handle -> domid -> bool -> (int64 * (int64 op= tion)) + -> string option array + -> string option array + =3D "stub_xc_domain_cpuid_set" +external domain_cpuid_apply: handle -> domid -> bool -> unit + =3D "stub_xc_domain_cpuid_apply" +external cpuid_check: (int64 * (int64 option)) -> string option array ->= (bool * string option array) + =3D "stub_xc_cpuid_check" + diff --git a/tools/ocaml/libs/xc/xc_cpufeature.h b/tools/ocaml/libs/xc/xc= _cpufeature.h new file mode 100644 index 0000000..047a6c9 --- /dev/null +++ b/tools/ocaml/libs/xc/xc_cpufeature.h @@ -0,0 +1,116 @@ +#ifndef __LIBXC_CPUFEATURE_H +#define __LIBXC_CPUFEATURE_H + +/* Intel-defined CPU features, CPUID level 0x00000001 (edx), word 0 */ +#define X86_FEATURE_FPU (0*32+ 0) /* Onboard FPU */ +#define X86_FEATURE_VME (0*32+ 1) /* Virtual Mode Extensions */ +#define X86_FEATURE_DE (0*32+ 2) /* Debugging Extensions */ +#define X86_FEATURE_PSE (0*32+ 3) /* Page Size Extensions */ +#define X86_FEATURE_TSC (0*32+ 4) /* Time Stamp Counter */ +#define X86_FEATURE_MSR (0*32+ 5) /* Model-Specific Registers, RDMSR, W= RMSR */ +#define X86_FEATURE_PAE (0*32+ 6) /* Physical Address Extensions */ +#define X86_FEATURE_MCE (0*32+ 7) /* Machine Check Architecture */ +#define X86_FEATURE_CX8 (0*32+ 8) /* CMPXCHG8 instruction */ +#define X86_FEATURE_APIC (0*32+ 9) /* Onboard APIC */ +#define X86_FEATURE_SEP (0*32+11) /* SYSENTER/SYSEXIT */ +#define X86_FEATURE_MTRR (0*32+12) /* Memory Type Range Registers */ +#define X86_FEATURE_PGE (0*32+13) /* Page Global Enable */ +#define X86_FEATURE_MCA (0*32+14) /* Machine Check Architecture */ +#define X86_FEATURE_CMOV (0*32+15) /* CMOV instruction (FCMOVCC and FCOM= I too if FPU present) */ +#define X86_FEATURE_PAT (0*32+16) /* Page Attribute Table */ +#define X86_FEATURE_PSE36 (0*32+17) /* 36-bit PSEs */ +#define X86_FEATURE_PN (0*32+18) /* Processor serial number */ +#define X86_FEATURE_CLFLSH (0*32+19) /* Supports the CLFLUSH instruction= */ +#define X86_FEATURE_DS (0*32+21) /* Debug Store */ +#define X86_FEATURE_ACPI (0*32+22) /* ACPI via MSR */ +#define X86_FEATURE_MMX (0*32+23) /* Multimedia Extensions */ +#define X86_FEATURE_FXSR (0*32+24) /* FXSAVE and FXRSTOR instructions (f= ast save and restore */ + /* of FPU context), and CR4.OSFXSR available */ +#define X86_FEATURE_XMM (0*32+25) /* Streaming SIMD Extensions */ +#define X86_FEATURE_XMM2 (0*32+26) /* Streaming SIMD Extensions-2 */ +#define X86_FEATURE_SELFSNOOP (0*32+27) /* CPU self snoop */ +#define X86_FEATURE_HT (0*32+28) /* Hyper-Threading */ +#define X86_FEATURE_ACC (0*32+29) /* Automatic clock control */ +#define X86_FEATURE_IA64 (0*32+30) /* IA-64 processor */ +#define X86_FEATURE_PBE (0*32+31) /* Pending Break Enable */ + +/* AMD-defined CPU features, CPUID level 0x80000001, word 1 */ +/* Don't duplicate feature flags which are redundant with Intel! */ +#define X86_FEATURE_SYSCALL (1*32+11) /* SYSCALL/SYSRET */ +#define X86_FEATURE_MP (1*32+19) /* MP Capable. */ +#define X86_FEATURE_NX (1*32+20) /* Execute Disable */ +#define X86_FEATURE_MMXEXT (1*32+22) /* AMD MMX extensions */ +#define X86_FEATURE_FFXSR (1*32+25) /* FFXSR instruction optimizat= ions */ +#define X86_FEATURE_PAGE1GB (1*32+26) /* 1Gb large page support */ +#define X86_FEATURE_RDTSCP (1*32+27) /* RDTSCP */ +#define X86_FEATURE_LM (1*32+29) /* Long Mode (x86-64) */ +#define X86_FEATURE_3DNOWEXT (1*32+30) /* AMD 3DNow! extensions */ +#define X86_FEATURE_3DNOW (1*32+31) /* 3DNow! */ + +/* Transmeta-defined CPU features, CPUID level 0x80860001, word 2 */ +#define X86_FEATURE_RECOVERY (2*32+ 0) /* CPU in recovery mode */ +#define X86_FEATURE_LONGRUN (2*32+ 1) /* Longrun power control */ +#define X86_FEATURE_LRTI (2*32+ 3) /* LongRun table interface */ + +/* Other features, Linux-defined mapping, word 3 */ +/* This range is used for feature bits which conflict or are synthesized= */ +#define X86_FEATURE_CXMMX (3*32+ 0) /* Cyrix MMX extensions */ +#define X86_FEATURE_K6_MTRR (3*32+ 1) /* AMD K6 nonstandard MTRRs */ +#define X86_FEATURE_CYRIX_ARR (3*32+ 2) /* Cyrix ARRs (=3D MTRRs) */ +#define X86_FEATURE_CENTAUR_MCR (3*32+ 3) /* Centaur MCRs (=3D MTRRs) */ +/* cpu types for specific tunings: */ +#define X86_FEATURE_K8 (3*32+ 4) /* Opteron, Athlon64 */ +#define X86_FEATURE_K7 (3*32+ 5) /* Athlon */ +#define X86_FEATURE_P3 (3*32+ 6) /* P3 */ +#define X86_FEATURE_P4 (3*32+ 7) /* P4 */ +#define X86_FEATURE_CONSTANT_TSC (3*32+ 8) /* TSC ticks at a constant ra= te */ + +/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ +#define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */ +#define X86_FEATURE_DTES64 (4*32+ 2) /* 64-bit Debug Store */ +#define X86_FEATURE_MWAIT (4*32+ 3) /* Monitor/Mwait support */ +#define X86_FEATURE_DSCPL (4*32+ 4) /* CPL Qualified Debug Store */ +#define X86_FEATURE_VMXE (4*32+ 5) /* Virtual Machine Extensions */ +#define X86_FEATURE_SMXE (4*32+ 6) /* Safer Mode Extensions */ +#define X86_FEATURE_EST (4*32+ 7) /* Enhanced SpeedStep */ +#define X86_FEATURE_TM2 (4*32+ 8) /* Thermal Monitor 2 */ +#define X86_FEATURE_SSSE3 (4*32+ 9) /* Supplemental Streaming SIMD Exten= sions-3 */ +#define X86_FEATURE_CID (4*32+10) /* Context ID */ +#define X86_FEATURE_CX16 (4*32+13) /* CMPXCHG16B */ +#define X86_FEATURE_XTPR (4*32+14) /* Send Task Priority Messages */ +#define X86_FEATURE_PDCM (4*32+15) /* Perf/Debug Capability MSR */ +#define X86_FEATURE_DCA (4*32+18) /* Direct Cache Access */ +#define X86_FEATURE_SSE4_1 (4*32+19) /* Streaming SIMD Extensions 4.1 */ +#define X86_FEATURE_SSE4_2 (4*32+20) /* Streaming SIMD Extensions 4.2 */ +#define X86_FEATURE_POPCNT (4*32+23) /* POPCNT instruction */ +#define X86_FEATURE_HYPERVISOR (4*32+31) /* Running under some hyperviso= r */ + +/* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word = 5 */ +#define X86_FEATURE_XSTORE (5*32+ 2) /* on-CPU RNG present (xstore insn)= */ +#define X86_FEATURE_XSTORE_EN (5*32+ 3) /* on-CPU RNG enabled */ +#define X86_FEATURE_XCRYPT (5*32+ 6) /* on-CPU crypto (xcrypt insn) */ +#define X86_FEATURE_XCRYPT_EN (5*32+ 7) /* on-CPU crypto enabled */ +#define X86_FEATURE_ACE2 (5*32+ 8) /* Advanced Cryptography Engine v2 */ +#define X86_FEATURE_ACE2_EN (5*32+ 9) /* ACE v2 enabled */ +#define X86_FEATURE_PHE (5*32+ 10) /* PadLock Hash Engine */ +#define X86_FEATURE_PHE_EN (5*32+ 11) /* PHE enabled */ +#define X86_FEATURE_PMM (5*32+ 12) /* PadLock Montgomery Multiplier */ +#define X86_FEATURE_PMM_EN (5*32+ 13) /* PMM enabled */ + +/* More extended AMD flags: CPUID level 0x80000001, ecx, word 6 */ +#define X86_FEATURE_LAHF_LM (6*32+ 0) /* LAHF/SAHF in long mode */ +#define X86_FEATURE_CMP_LEGACY (6*32+ 1) /* If yes HyperThreading not va= lid */ +#define X86_FEATURE_SVME (6*32+ 2) /* Secure Virtual Machine */ +#define X86_FEATURE_EXTAPICSPACE (6*32+ 3) /* Extended APIC space */ +#define X86_FEATURE_ALTMOVCR (6*32+ 4) /* LOCK MOV CR accesses CR+8 */ +#define X86_FEATURE_ABM (6*32+ 5) /* Advanced Bit Manipulation */ +#define X86_FEATURE_SSE4A (6*32+ 6) /* AMD Streaming SIMD Extensions-4a = */ +#define X86_FEATURE_MISALIGNSSE (6*32+ 7) /* Misaligned SSE Access */ +#define X86_FEATURE_3DNOWPF (6*32+ 8) /* 3DNow! Prefetch */ +#define X86_FEATURE_OSVW (6*32+ 9) /* OS Visible Workaround */ +#define X86_FEATURE_IBS (6*32+ 10) /* Instruction Based Sampling */ +#define X86_FEATURE_SSE5 (6*32+ 11) /* AMD Streaming SIMD Extensions-5 *= / +#define X86_FEATURE_SKINIT (6*32+ 12) /* SKINIT, STGI/CLGI, DEV */ +#define X86_FEATURE_WDT (6*32+ 13) /* Watchdog Timer */ + +#endif /* __LIBXC_CPUFEATURE_H */ diff --git a/tools/ocaml/libs/xc/xc_cpuid.h b/tools/ocaml/libs/xc/xc_cpui= d.h new file mode 100644 index 0000000..43743ef --- /dev/null +++ b/tools/ocaml/libs/xc/xc_cpuid.h @@ -0,0 +1,285 @@ +#ifndef XC_CPUID_H +#define XC_CPUID_H + +#ifdef XEN_DOMCTL_set_cpuid + +#include "xc_cpufeature.h" + +#define bitmaskof(idx) (1u << ((idx) & 31)) +#define clear_bit(idx, dst) ((dst) &=3D ~(1u << ((idx) & 31))) +#define set_bit(idx, dst) ((dst) |=3D (1u << ((idx) & 31))) + +#define DEF_MAX_BASE 0x00000004u +#define DEF_MAX_EXT 0x80000008u + +static void xc_cpuid(uint32_t eax, uint32_t ecx, uint32_t regs[4]) +{ + unsigned int realecx =3D (ecx =3D=3D XEN_CPUID_INPUT_UNUSED) ? 0 : ecx; + asm ( +#ifdef __i386__ + "push %%ebx; cpuid; mov %%ebx,%1; pop %%ebx" +#else + "push %%rbx; cpuid; mov %%ebx,%1; pop %%rbx" +#endif + : "=3Da" (regs[0]), "=3Dr" (regs[1]), "=3Dc" (regs[2]), "=3Dd" (reg= s[3]) + : "0" (eax), "2" (realecx)); +} + +enum { CPU_BRAND_INTEL, CPU_BRAND_AMD, CPU_BRAND_UNKNOWN }; + +static int xc_cpuid_brand_get(void) +{ + uint32_t regs[4]; + char str[13]; + uint32_t *istr =3D (uint32_t *) str; + + xc_cpuid(0, 0, regs); + istr[0] =3D regs[1]; + istr[1] =3D regs[3]; + istr[2] =3D regs[2]; + str[12] =3D '\0'; + if (strcmp(str, "AuthenticAMD") =3D=3D 0) { + return CPU_BRAND_AMD; + } else if (strcmp(str, "GenuineIntel") =3D=3D 0) { + return CPU_BRAND_INTEL; + } else + return CPU_BRAND_UNKNOWN; +} + +static int hypervisor_is_64bit(int xc) +{ + xen_capabilities_info_t xen_caps; + return ((xc_version(xc, XENVER_capabilities, &xen_caps) =3D=3D 0) && + (strstr(xen_caps, "x86_64") !=3D NULL)); +} + +static void do_hvm_cpuid_policy(int xc, int domid, uint32_t input, uint3= 2_t regs[4]) +{ + unsigned long is_pae; + int brand; + + /* pae ? */ + xc_get_hvm_param(xc, domid, HVM_PARAM_PAE_ENABLED, &is_pae); + is_pae =3D !!is_pae; + + switch (input) { + case 0x00000000: + if (regs[0] > DEF_MAX_BASE) + regs[0] =3D DEF_MAX_BASE; + break; + case 0x00000001: + regs[2] &=3D (bitmaskof(X86_FEATURE_XMM3) | + bitmaskof(X86_FEATURE_SSSE3) | + bitmaskof(X86_FEATURE_CX16) | + bitmaskof(X86_FEATURE_SSE4_1) | + bitmaskof(X86_FEATURE_SSE4_2) | + bitmaskof(X86_FEATURE_POPCNT)); + + regs[2] |=3D bitmaskof(X86_FEATURE_HYPERVISOR); + + regs[3] &=3D (bitmaskof(X86_FEATURE_FPU) | + bitmaskof(X86_FEATURE_VME) | + bitmaskof(X86_FEATURE_DE) | + bitmaskof(X86_FEATURE_PSE) | + bitmaskof(X86_FEATURE_TSC) | + bitmaskof(X86_FEATURE_MSR) | + bitmaskof(X86_FEATURE_PAE) | + bitmaskof(X86_FEATURE_MCE) | + bitmaskof(X86_FEATURE_CX8) | + bitmaskof(X86_FEATURE_APIC) | + bitmaskof(X86_FEATURE_SEP) | + bitmaskof(X86_FEATURE_MTRR) | + bitmaskof(X86_FEATURE_PGE) | + bitmaskof(X86_FEATURE_MCA) | + bitmaskof(X86_FEATURE_CMOV) | + bitmaskof(X86_FEATURE_PAT) | + bitmaskof(X86_FEATURE_CLFLSH) | + bitmaskof(X86_FEATURE_MMX) | + bitmaskof(X86_FEATURE_FXSR) | + bitmaskof(X86_FEATURE_XMM) | + bitmaskof(X86_FEATURE_XMM2)); + /* We always support MTRR MSRs. */ + regs[3] |=3D bitmaskof(X86_FEATURE_MTRR); + + if (!is_pae) + clear_bit(X86_FEATURE_PAE, regs[3]); + break; + case 0x80000000: + if (regs[0] > DEF_MAX_EXT) + regs[0] =3D DEF_MAX_EXT; + break; + case 0x80000001: + if (!is_pae) + clear_bit(X86_FEATURE_NX, regs[3]); + break; + case 0x80000008: + regs[0] &=3D 0x0000ffffu; + regs[1] =3D regs[2] =3D regs[3] =3D 0; + break; + case 0x00000002: /* Intel cache info (dumped by AMD policy) */ + case 0x00000004: /* Intel cache info (dumped by AMD policy) */ + case 0x80000002: /* Processor name string */ + case 0x80000003: /* ... continued */ + case 0x80000004: /* ... continued */ + case 0x80000005: /* AMD L1 cache/TLB info (dumped by Intel policy) */ + case 0x80000006: /* AMD L2/3 cache/TLB info ; Intel L2 cache features *= / + break; + default: + regs[0] =3D regs[1] =3D regs[2] =3D regs[3] =3D 0; + break; + } +=09 + brand =3D xc_cpuid_brand_get(); + if (brand =3D=3D CPU_BRAND_AMD) { + switch (input) { + case 0x00000001: + /* Mask Intel-only features. */ + regs[2] &=3D ~(bitmaskof(X86_FEATURE_SSSE3) | + bitmaskof(X86_FEATURE_SSE4_1) | + bitmaskof(X86_FEATURE_SSE4_2)); + break; + + case 0x00000002: + case 0x00000004: + regs[0] =3D regs[1] =3D regs[2] =3D 0; + break; + + case 0x80000001: { + int is_64bit =3D hypervisor_is_64bit(xc) && is_pae; + + if (!is_pae) + clear_bit(X86_FEATURE_PAE, regs[3]); + clear_bit(X86_FEATURE_PSE36, regs[3]); + + /* Filter all other features according to a whitelist. */ + regs[2] &=3D ((is_64bit ? bitmaskof(X86_FEATURE_LAHF_LM) : 0) | + bitmaskof(X86_FEATURE_ALTMOVCR) | + bitmaskof(X86_FEATURE_ABM) | + bitmaskof(X86_FEATURE_SSE4A) | + bitmaskof(X86_FEATURE_MISALIGNSSE) | + bitmaskof(X86_FEATURE_3DNOWPF)); + regs[3] &=3D (0x0183f3ff | /* features shared with 0x00000001:EDX */ + (is_pae ? bitmaskof(X86_FEATURE_NX) : 0) | + (is_64bit ? bitmaskof(X86_FEATURE_LM) : 0) | + bitmaskof(X86_FEATURE_SYSCALL) | + bitmaskof(X86_FEATURE_MP) | + bitmaskof(X86_FEATURE_MMXEXT) | + bitmaskof(X86_FEATURE_FFXSR) | + bitmaskof(X86_FEATURE_3DNOW) | + bitmaskof(X86_FEATURE_3DNOWEXT)); + break; + } + } + } else if (brand =3D=3D CPU_BRAND_INTEL) { + switch (input) { + case 0x00000001: + /* Mask AMD-only features. */ + regs[2] &=3D ~(bitmaskof(X86_FEATURE_POPCNT)); + break; + + case 0x00000004: + regs[0] &=3D 0x3FF; + regs[3] &=3D 0x3FF; + break; + + case 0x80000001: + { + int is_64bit =3D hypervisor_is_64bit(xc) && is_pae; + + /* Only a few features are advertised in Intel's 0x80000001. */ + regs[2] &=3D (is_64bit ? bitmaskof(X86_FEATURE_LAHF_LM) : 0); + regs[3] &=3D ((is_pae ? bitmaskof(X86_FEATURE_NX) : 0) | + (is_64bit ? bitmaskof(X86_FEATURE_LM) : 0) | + (is_64bit ? bitmaskof(X86_FEATURE_SYSCALL) : 0)); + break; + } + case 0x80000005: + { + regs[0] =3D regs[1] =3D regs[2] =3D 0; + break; + } + } + } +} + +static void do_pv_cpuid_policy(int xc, int domid, uint32_t input, uint32= _t regs[4]) +{ + int brand; + int guest_64_bits, xen_64_bits; + int ret; +=09 + ret =3D xc_domain_get_machine_address_size(xc, domid); + if (ret < 0) + return; + guest_64_bits =3D (ret =3D=3D 64); + xen_64_bits =3D hypervisor_is_64bit(xc); + brand =3D xc_cpuid_brand_get(); + + if ((input & 0x7fffffff) =3D=3D 1) { + clear_bit(X86_FEATURE_VME, regs[3]); + clear_bit(X86_FEATURE_PSE, regs[3]); + clear_bit(X86_FEATURE_PGE, regs[3]); + clear_bit(X86_FEATURE_MCE, regs[3]); + clear_bit(X86_FEATURE_MCA, regs[3]); + clear_bit(X86_FEATURE_MTRR, regs[3]); + clear_bit(X86_FEATURE_PSE36, regs[3]); + } + + switch (input) { + case 1: + if (!xen_64_bits || brand =3D=3D CPU_BRAND_AMD) + clear_bit(X86_FEATURE_SEP, regs[3]); + clear_bit(X86_FEATURE_DS, regs[3]); + clear_bit(X86_FEATURE_ACC, regs[3]); + clear_bit(X86_FEATURE_PBE, regs[3]); + + clear_bit(X86_FEATURE_DTES64, regs[2]); + clear_bit(X86_FEATURE_MWAIT, regs[2]); + clear_bit(X86_FEATURE_DSCPL, regs[2]); + clear_bit(X86_FEATURE_VMXE, regs[2]); + clear_bit(X86_FEATURE_SMXE, regs[2]); + clear_bit(X86_FEATURE_EST, regs[2]); + clear_bit(X86_FEATURE_TM2, regs[2]); + if (!guest_64_bits) + clear_bit(X86_FEATURE_CX16, regs[2]); + clear_bit(X86_FEATURE_XTPR, regs[2]); + clear_bit(X86_FEATURE_PDCM, regs[2]); + clear_bit(X86_FEATURE_DCA, regs[2]); + break; + case 0x80000001: + if (!guest_64_bits) { + clear_bit(X86_FEATURE_LM, regs[3]); + clear_bit(X86_FEATURE_LAHF_LM, regs[2]); + if (brand !=3D CPU_BRAND_AMD) + clear_bit(X86_FEATURE_SYSCALL, regs[3]); + } else + set_bit(X86_FEATURE_SYSCALL, regs[3]); + clear_bit(X86_FEATURE_PAGE1GB, regs[3]); + clear_bit(X86_FEATURE_RDTSCP, regs[3]); + + clear_bit(X86_FEATURE_SVME, regs[2]); + clear_bit(X86_FEATURE_OSVW, regs[2]); + clear_bit(X86_FEATURE_IBS, regs[2]); + clear_bit(X86_FEATURE_SKINIT, regs[2]); + clear_bit(X86_FEATURE_WDT, regs[2]); + break; + case 5: /* MONITOR/MWAIT */ + case 0xa: /* Architectural Performance Monitor Features */ + case 0x8000000a: /* SVM revision and features */ + case 0x8000001b: /* Instruction Based Sampling */ + regs[0] =3D regs[1] =3D regs[2] =3D regs[3] =3D 0; + break; + } +} + +static void do_cpuid_policy(int xc, int domid, int hvm, uint32_t input, = uint32_t regs[4]) +{ + if (hvm) + do_hvm_cpuid_policy(xc, domid, input, regs); + else + do_pv_cpuid_policy(xc, domid, input, regs); +} + +#endif + +#endif diff --git a/tools/ocaml/libs/xc/xc_e820.h b/tools/ocaml/libs/xc/xc_e820.= h new file mode 100644 index 0000000..52bbb0f --- /dev/null +++ b/tools/ocaml/libs/xc/xc_e820.h @@ -0,0 +1,20 @@ +#ifndef __XC_E820_H__ +#define __XC_E820_H__ + +#include + +/* + * PC BIOS standard E820 types and structure. + */ +#define E820_RAM 1 +#define E820_RESERVED 2 +#define E820_ACPI 3 +#define E820_NVS 4 + +struct e820entry { + uint64_t addr; + uint64_t size; + uint32_t type; +} __attribute__((packed)); + +#endif /* __XC_E820_H__ */ diff --git a/tools/ocaml/libs/xc/xc_lib.c b/tools/ocaml/libs/xc/xc_lib.c new file mode 100644 index 0000000..7fffc43 --- /dev/null +++ b/tools/ocaml/libs/xc/xc_lib.c @@ -0,0 +1,1502 @@ +/* + * Copyright (C) 2006-2007 XenSource Ltd. + * Copyright (C) 2008 Citrix Ltd. + * Author Vincent Hanquez + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as publis= hed + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "xc.h" + +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE-1)) + +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) + +#define DECLARE_DOMCTL(_cmd, _domain) \ + struct xen_domctl domctl =3D { \ + .cmd =3D _cmd, \ + .domain =3D _domain, \ + .interface_version =3D XEN_DOMCTL_INTERFACE_VERSION, \ + } + +#define DECLARE_SYSCTL(_cmd) \ + struct xen_sysctl sysctl =3D { \ + .cmd =3D _cmd, \ + .interface_version =3D XEN_SYSCTL_INTERFACE_VERSION, \ + } + +#define DECLARE_HYPERCALL2(_cmd, _arg0, _arg1) \ + privcmd_hypercall_t hypercall =3D { \ + .op =3D _cmd, \ + .arg[0] =3D (unsigned long) _arg0,\ + .arg[1] =3D (unsigned long) _arg1,\ + } +#define DECLARE_HYPERCALL0(_cmd) DECLARE_HYPERCALL2(_cmd, 0, 0); +#define DECLARE_HYPERCALL1(_cmd, _arg0) DECLARE_HYPERCALL2(_cmd, _arg0, = 0); + +/*---- Errors handlings ----*/ +#ifndef WITHOUT_GOOD_ERROR +#define ERROR_STRLEN 256 + +static char __error_str[ERROR_STRLEN]; + +char * xc_error_get(void) +{ + return __error_str; +} + +static void xc_error_set(const char *fmt, ...) +{ + va_list ap; + char __errordup[ERROR_STRLEN]; + + va_start(ap, fmt); + vsnprintf(__errordup, ERROR_STRLEN, fmt, ap); + va_end(ap); + memcpy(__error_str, __errordup, ERROR_STRLEN); +} + +static void xc_error_dom_set(unsigned int domid, const char *fmt, ...) +{ + va_list ap; + char __errordup[ERROR_STRLEN]; + int i; + + i =3D snprintf(__errordup, ERROR_STRLEN, "domain %u - ", domid); + va_start(ap, fmt); + i +=3D vsnprintf(__errordup + i, ERROR_STRLEN - i, fmt, ap); + va_end(ap); + snprintf(__errordup + i, ERROR_STRLEN - i, + " failed: %s", xc_error_get()); + memcpy(__error_str, __errordup, ERROR_STRLEN); +} + +void xc_error_clear(void) +{ + memset(__error_str, '\0', ERROR_STRLEN); +} +#else +char * xc_error_get(void) +{ + return ""; +} +#define xc_error_set(fmt, ...) do {} while (0) +#define xc_error_dom_set(id, fmt, ...) do {} while (0) +#define xc_error_clear() do {} while (0) +#endif + +#define xc_error_hypercall(_h, _r) \ + xc_error_set("hypercall %lld fail: %d: %s (ret %d)", _h.op, errno, errn= o ? strerror(errno) : strerror(-_r), _r) + +int xc_using_injection(void) +{ + return 0; +} + +/*---- Trivia ----*/ +int xc_interface_open(void) +{ + int fd, ret; + + fd =3D open("/proc/xen/privcmd", O_RDWR); + if (fd =3D=3D -1) { + xc_error_set("open /proc/xen/privcmd failed: %s", + strerror(errno)); + return -1; + } + + ret =3D fcntl(fd, F_GETFD); + if (ret < 0) { + xc_error_set("cannot get handle flags: %s", + strerror(errno)); + goto out; + } + + ret =3D fcntl(fd, F_SETFD, ret | FD_CLOEXEC); + if (ret < 0) { + xc_error_set("cannot set handle flags: %s", + strerror(errno)); + goto out; + } + + return fd; +out: + close(fd); + return -1; +} + +int xc_interface_close(int handle) +{ + int ret; + + ret =3D close(handle); + if (ret !=3D 0) + xc_error_set("close xc failed: %s", strerror(errno)); + return ret; +} + +/*---- Low private operations ----*/ +static int do_xen_hypercall(int handle, privcmd_hypercall_t *hypercall) +{ + return ioctl(handle, IOCTL_PRIVCMD_HYPERCALL, (unsigned long) hypercall= ); +} + +static int do_domctl(int handle, struct xen_domctl *domctl) +{ + int ret; + DECLARE_HYPERCALL1(__HYPERVISOR_domctl, domctl); + + if (mlock(domctl, sizeof(*domctl)) !=3D 0) { + xc_error_set("mlock failed: %s", strerror(errno)); + return -1; + } + + ret =3D do_xen_hypercall(handle, &hypercall); + if (ret < 0) + xc_error_hypercall(hypercall, ret); + + munlock(domctl, sizeof(*domctl)); + return ret; +} + +static int do_sysctl(int handle, struct xen_sysctl *sysctl) +{ + int ret; + DECLARE_HYPERCALL1(__HYPERVISOR_sysctl, sysctl); + + if (mlock(sysctl, sizeof(*sysctl)) !=3D 0) { + xc_error_set("mlock failed: %s", strerror(errno)); + return -1; + } + + ret =3D do_xen_hypercall(handle, &hypercall); + if (ret < 0) + xc_error_hypercall(hypercall, ret); + + munlock(sysctl, sizeof(*sysctl)); + return ret; +} + +static int do_evtchnctl(int handle, int cmd, void *arg, size_t arg_size) +{ + DECLARE_HYPERCALL2(__HYPERVISOR_event_channel_op, cmd, arg); + int ret; + + if (mlock(arg, arg_size) !=3D 0) { + xc_error_set("mlock failed: %s", strerror(errno)); + return -1; + } + + ret =3D do_xen_hypercall(handle, &hypercall); + if (ret < 0) + xc_error_hypercall(hypercall, ret); + munlock(arg, arg_size); + return ret; +} + +static int do_memctl_reservation(int handle, int cmd, + struct xen_memory_reservation *reservat= ion) +{ + int ret; + DECLARE_HYPERCALL2(__HYPERVISOR_memory_op, cmd, reservation); + xen_pfn_t *extent_start; + + if (cmd !=3D XENMEM_increase_reservation && + cmd !=3D XENMEM_decrease_reservation && + cmd !=3D XENMEM_populate_physmap) { + xc_error_set("do_memctl_reservation: unknown cmd %d", cmd); + return -EINVAL; + } + + if (mlock(reservation, sizeof(*reservation)) =3D=3D -1) { + xc_error_set("mlock failed: %s", strerror(errno)); + return -ENOMEM; + } + get_xen_guest_handle(extent_start, reservation->extent_start); + if (extent_start && mlock(extent_start, reservation->nr_extents + * sizeof(xen_pfn_t)) =3D=3D -1) { + xc_error_set("mlock failed: %s", strerror(errno)); + munlock(reservation, sizeof(*reservation)); + return -3; + } + + ret =3D do_xen_hypercall(handle, &hypercall); + if (ret) + xc_error_hypercall(hypercall, ret); + munlock(extent_start, reservation->nr_extents * sizeof(xen_pfn_t)); + get_xen_guest_handle(extent_start, reservation->extent_start); + munlock(reservation, sizeof(*reservation)); + return ret; +} + +static int do_ioctl(int handle, int cmd, void *arg) +{ + return ioctl(handle, cmd, arg); +} + +static void * do_mmap(void *start, size_t length, int prot, int flags, + int fd, off_t offset) +{ + return mmap(start, length, prot, flags, fd, offset); +} + +int xc_get_hvm_param(int handle, unsigned int domid, + int param, unsigned long *value) +{ + struct xen_hvm_param arg =3D { + .domid =3D domid, + .index =3D param, + }; + DECLARE_HYPERCALL2(__HYPERVISOR_hvm_op, HVMOP_get_param, + (unsigned long) &arg); + int ret; + + if (mlock(&arg, sizeof(arg)) =3D=3D -1) { + xc_error_set("mlock failed: %s", strerror(errno)); + return -1; + } + + ret =3D do_xen_hypercall(handle, &hypercall); + if (ret) + xc_error_hypercall(hypercall, ret); + *value =3D arg.value; + munlock(&arg, sizeof(arg)); + return ret; +} + +static int xc_set_hvm_param(int handle, unsigned int domid, + int param, unsigned long value) +{ + struct xen_hvm_param arg =3D { + .domid =3D domid, + .index =3D param, + .value =3D value, + }; + DECLARE_HYPERCALL2(__HYPERVISOR_hvm_op, HVMOP_set_param, (unsigned long= ) &arg); + int ret; + + if (mlock(&arg, sizeof(arg)) =3D=3D -1) { + xc_error_set("mlock failed: %s", strerror(errno)); + return -1; + } + + ret =3D do_xen_hypercall(handle, &hypercall); + if (ret) + xc_error_hypercall(hypercall, ret); + munlock(&arg, sizeof(arg)); + return ret; +} + + +/*---- XC API ----*/ +int xc_domain_create(int handle, unsigned int ssidref, + xen_domain_handle_t dhandle, + unsigned int flags, unsigned int *pdomid) +{ + int ret; + DECLARE_DOMCTL(XEN_DOMCTL_createdomain, *pdomid); + domctl.u.createdomain.ssidref =3D ssidref; + domctl.u.createdomain.flags =3D flags; + memcpy(domctl.u.createdomain.handle, dhandle, sizeof(xen_domain_handle_= t)); + + ret =3D do_domctl(handle, &domctl); + if (ret !=3D 0) { + xc_error_set("creating domain failed: %s", xc_error_get()); + return ret; + } + *pdomid =3D domctl.domain; + return 0; +} + +int xc_domain_pause(int handle, unsigned int domid) +{ + int ret; + DECLARE_DOMCTL(XEN_DOMCTL_pausedomain, domid); + + ret =3D do_domctl(handle, &domctl); + if (ret !=3D 0) + xc_error_dom_set(domid, "pause"); + return ret; +} + +int xc_domain_unpause(int handle, unsigned int domid) +{ + int ret; + DECLARE_DOMCTL(XEN_DOMCTL_unpausedomain, domid); + + ret =3D do_domctl(handle, &domctl); + if (ret !=3D 0) + xc_error_dom_set(domid, "unpause"); + return ret; +} + +/* return 1 if hvm domain got pv driver, 0 if not. -1 is error occurs */ +int xc_hvm_check_pvdriver(int handle, unsigned int domid) +{ + int ret; + unsigned long irq =3D 0; + xc_domaininfo_t info; + + ret =3D xc_domain_getinfolist(handle, domid, 1, &info); + if (ret !=3D 1) { + xc_error_set("domain getinfo failed: %s", strerror(errno)); + xc_error_dom_set(domid, "hvm_check_pvdriver"); + return -1; + } + + if (!(info.flags & XEN_DOMINF_hvm_guest)) { + xc_error_set("domain is not hvm"); + xc_error_dom_set(domid, "hvm_check_pvdriver"); + return -1; + } + xc_get_hvm_param(handle, domid, HVM_PARAM_CALLBACK_IRQ, &irq); + return irq; +} + +static int modify_returncode_register(int handle, unsigned int domid) +{ + int ret; + xc_domaininfo_t info; + xen_capabilities_info_t caps; + vcpu_guest_context_any_t context; + + ret =3D xc_domain_getinfolist(handle, domid, 1, &info); + if (ret !=3D 1) { + xc_error_set("domain getinfo failed: %s", strerror(errno)); + return -1; + } + + /* HVM guests without PV drivers do not have a return code to modify */ + if (info.flags & XEN_DOMINF_hvm_guest) { + unsigned long irq =3D 0; + xc_get_hvm_param(handle, domid, HVM_PARAM_CALLBACK_IRQ, &irq); + if (!irq) + return 0; + } + + ret =3D xc_version(handle, XENVER_capabilities, &caps); + if (ret) { + xc_error_set("could not get Xen capabilities"); + return ret; + } + + ret =3D xc_vcpu_getcontext(handle, domid, 0, &context); + if (ret) { + xc_error_set("could not get vcpu 0 context"); + return ret; + } + + if (!(info.flags & XEN_DOMINF_hvm_guest)) + context.c.user_regs.eax =3D 1; + else if (strstr(caps, "x86_64")) + context.x64.user_regs.eax =3D 1; + else + context.x32.user_regs.eax =3D 1; + + ret =3D xc_vcpu_setcontext(handle, domid, 0, &context); + if (ret) { + xc_error_set("could not set vcpu 0 context"); + return ret; + } + return 0; +} + +int xc_domain_resume_fast(int handle, unsigned int domid) +{ + int ret; + DECLARE_DOMCTL(XEN_DOMCTL_resumedomain, domid); + + ret =3D modify_returncode_register(handle, domid); + if (ret !=3D 0) { + xc_error_dom_set(domid, "resume_fast"); + return ret; + } + + ret =3D do_domctl(handle, &domctl); + if (ret !=3D 0) + xc_error_dom_set(domid, "resume_fast"); + return ret; +} + +int xc_domain_destroy(int handle, unsigned int domid) +{ + int ret; + DECLARE_DOMCTL(XEN_DOMCTL_destroydomain, domid); + + do { + ret =3D do_domctl(handle, &domctl); + } while (ret && (errno =3D=3D EAGAIN)); + if (ret !=3D 0) + xc_error_dom_set(domid, "destroy"); + return ret; +} + +int xc_domain_shutdown(int handle, int domid, int reason) +{ + sched_remote_shutdown_t arg =3D { + .domain_id =3D domid, + .reason =3D reason, + }; + DECLARE_HYPERCALL2(__HYPERVISOR_sched_op, SCHEDOP_remote_shutdown, &arg= ); + int ret; + + if (mlock(&arg, sizeof(arg)) !=3D 0) { + xc_error_set("mlock failed: %s", strerror(errno)); + xc_error_dom_set(domid, "shutdown %d", reason); + return -1; + } + + ret =3D do_xen_hypercall(handle, &hypercall); + if (ret < 0) { + xc_error_hypercall(hypercall, ret); + xc_error_dom_set(domid, "shutdown %d", reason); + } + munlock(&arg, sizeof(arg)); + return ret; +} + +int xc_vcpu_setaffinity(int handle, unsigned int domid, int vcpu, + uint64_t cpumap) +{ + int ret; + DECLARE_DOMCTL(XEN_DOMCTL_setvcpuaffinity, domid); + domctl.u.vcpuaffinity.vcpu =3D vcpu; + domctl.u.vcpuaffinity.cpumap.nr_cpus =3D sizeof(cpumap) * 8; + + set_xen_guest_handle(domctl.u.vcpuaffinity.cpumap.bitmap, (uint8_t *) &= cpumap); + + if (mlock(&cpumap, sizeof(cpumap)) !=3D 0) { + xc_error_set("mlock failed: %s", strerror(errno)); + xc_error_dom_set(domid, "vcpu %d set affinity", vcpu); + return -1; + } + + ret =3D do_domctl(handle, &domctl); + if (ret < 0) + xc_error_dom_set(domid, "vcpu %d set affinity", vcpu); + munlock(&cpumap, sizeof(cpumap)); + return ret; +} + +int xc_vcpu_getaffinity(int handle, unsigned int domid, int vcpu, + uint64_t *cpumap) +{ + int ret; + DECLARE_DOMCTL(XEN_DOMCTL_getvcpuaffinity, domid); + domctl.u.vcpuaffinity.vcpu =3D vcpu; + domctl.u.vcpuaffinity.cpumap.nr_cpus =3D sizeof(*cpumap) * 8; + + set_xen_guest_handle(domctl.u.vcpuaffinity.cpumap.bitmap, cpumap); + + if (mlock(cpumap, sizeof(*cpumap)) !=3D 0) { + xc_error_set("mlock failed: %s", strerror(errno)); + xc_error_dom_set(domid, "vcpu %d get affinity", vcpu); + return -1; + } + + ret =3D do_domctl(handle, &domctl); + if (ret < 0) + xc_error_dom_set(domid, "vcpu %d get affinity", vcpu); + munlock(cpumap, sizeof(*cpumap)); + return ret; +} + +int xc_vcpu_context_get(int handle, unsigned int domid, unsigned short v= cpu, + struct vcpu_guest_context *ctxt) +{ + int ret; + DECLARE_DOMCTL(XEN_DOMCTL_getvcpucontext, domid); + domctl.u.vcpucontext.vcpu =3D vcpu; + + set_xen_guest_handle(domctl.u.vcpucontext.ctxt, ctxt); + + if (mlock(ctxt, sizeof(struct vcpu_guest_context)) !=3D 0) { + xc_error_set("mlock failed: %s", strerror(errno)); + xc_error_dom_set(domid, "vcpu %d get context", vcpu); + return -1; + } + + ret =3D do_domctl(handle, &domctl); + if (ret < 0) + xc_error_dom_set(domid, "vcpu %d get context", vcpu); + munlock(ctxt, sizeof(struct vcpu_guest_context)); + + return ret; +} + +int xc_domain_getinfolist(int handle, unsigned int first_domain, + unsigned int max_domains, xc_domaininfo_t *inf= o) +{ + int ret; + DECLARE_SYSCTL(XEN_SYSCTL_getdomaininfolist); + sysctl.u.getdomaininfolist.first_domain =3D first_domain; + sysctl.u.getdomaininfolist.max_domains =3D max_domains; + set_xen_guest_handle(sysctl.u.getdomaininfolist.buffer, info); + + if (mlock(info, max_domains * sizeof(xc_domaininfo_t)) !=3D 0) { + xc_error_set("getinfolist(%d, %u, %u, %x (%d)) failed: mlock failed: %= s", + handle, first_domain, max_domains, info, sizeof(xc_domaininfo_t)= , + strerror(errno)); + return -1; + } + + ret =3D do_sysctl(handle, &sysctl); + if (ret < 0) + xc_error_set("getinfolist(%d, %u, %u, %x (%d)) failed: %s",=20 + handle, first_domain, max_domains, info, sizeof(xc_domaininfo_t)= , + xc_error_get()); + else + ret =3D sysctl.u.getdomaininfolist.num_domains; + + munlock(info, max_domains * sizeof(xc_domaininfo_t)); + return ret; +} + +int xc_domain_getinfo(int handle, unsigned int domid, xc_domaininfo_t *i= nfo) +{ + int ret; + ret =3D xc_domain_getinfolist(handle, domid, 1, info); + if (ret !=3D 1) { + xc_error_set("getinfo failed: domain %d: %s", domid, xc_error_get()); + return -1; + } + + /* If the requested domain didn't exist but there exists one with a=20 + higher domain ID, this will be returned. We consider this an error s= ince + we only wanted info about a specific domain. */ + if (info->domain !=3D domid) { + xc_error_set("getinfo failed: domain %d nolonger exists", domid); + return -1; + } + + return 0; +} + +int xc_domain_setmaxmem(int handle, unsigned int domid, unsigned int max= _memkb) +{ + DECLARE_DOMCTL(XEN_DOMCTL_max_mem, domid); + domctl.u.max_mem.max_memkb =3D max_memkb; + int ret; + + ret =3D do_domctl(handle, &domctl); + if (ret < 0) + xc_error_dom_set(domid, "set max memory to %u", max_memkb); + return ret; +} + +int xc_domain_set_memmap_limit(int handle, unsigned int domid, + unsigned long map_limitkb) +{ + int ret; + struct xen_foreign_memory_map fmap =3D { + .domid =3D domid, + .map =3D { .nr_entries =3D 1 } + }; + struct e820entry e820 =3D { + .addr =3D 0, + .size =3D (uint64_t)map_limitkb << 10, + .type =3D E820_RAM + }; + DECLARE_HYPERCALL2(__HYPERVISOR_memory_op, XENMEM_set_memory_map, &fmap= ); + + set_xen_guest_handle(fmap.map.buffer, &e820); + + if (mlock(&fmap, sizeof(fmap)) !=3D 0) { + xc_error_set("set_memmap_limit failed: mlock failed: %s", + strerror(errno)); + return -1; + } + + if (mlock(&e820, sizeof(e820)) !=3D 0) { + xc_error_set("set_memmap_limit failed: mlock failed: %s", + strerror(errno)); + munlock(&fmap, sizeof(fmap)); + return -1; + } + + ret =3D do_xen_hypercall(handle, &hypercall); + if (ret) + xc_error_hypercall(hypercall, ret); + + munlock(&e820, sizeof(e820)); + munlock(&fmap, sizeof(fmap)); + return ret; +} + +int xc_domain_set_time_offset(int handle, unsigned int domid, int time_o= ffset) +{ + DECLARE_DOMCTL(XEN_DOMCTL_settimeoffset, domid); + domctl.u.settimeoffset.time_offset_seconds =3D time_offset; + int ret; + + ret =3D do_domctl(handle, &domctl); + if (ret < 0) + xc_error_dom_set(domid, "set time offset %d", time_offset); + return ret; +} + +int xc_domain_memory_increase_reservation(int handle, unsigned int domid= , + unsigned long nr_extents, + unsigned int extent_order, + unsigned int address_bits, + xen_pfn_t *extent_start) +{ + int ret; + struct xen_memory_reservation reservation =3D { + .nr_extents =3D nr_extents, + .extent_order =3D extent_order, + .COMPAT_FIELD_ADDRESS_BITS =3D address_bits, + .domid =3D domid + }; + + set_xen_guest_handle(reservation.extent_start, extent_start); + + ret =3D do_memctl_reservation(handle, XENMEM_increase_reservation, + &reservation); + if (ret !=3D nr_extents) { + xc_error_dom_set(domid, "increase reservation to %lu", + nr_extents); + return (ret >=3D 0) ? -1 : ret; + } + return 0; +} + +int xc_domain_memory_decrease_reservation(int handle, unsigned int domid= , + unsigned long nr_extents, + unsigned int extent_order, + unsigned int address_bits, + xen_pfn_t *extent_start) +{ + int ret; + struct xen_memory_reservation reservation =3D { + .nr_extents =3D nr_extents, + .extent_order =3D extent_order, + .COMPAT_FIELD_ADDRESS_BITS =3D 0, + .domid =3D domid + }; + + set_xen_guest_handle(reservation.extent_start, extent_start); + if (!extent_start) { + xc_error_set("decrease reservation: extent start is NULL"); + return -EINVAL; + } + + ret =3D do_memctl_reservation(handle, XENMEM_decrease_reservation, + &reservation); + if (ret < nr_extents) { + xc_error_dom_set(domid, "decrease reservation to %lu", + nr_extents); + return (ret >=3D 0) ? -1 : ret; + } + return 0; +} + +int xc_domain_memory_populate_physmap(int handle, unsigned int domid, + unsigned long nr_extents, + unsigned int extent_order, + unsigned int address_bits, + xen_pfn_t *extent_start) +{ + int ret; + struct xen_memory_reservation reservation =3D { + .nr_extents =3D nr_extents, + .extent_order =3D extent_order, + .COMPAT_FIELD_ADDRESS_BITS =3D address_bits, + .domid =3D domid + }; + + set_xen_guest_handle(reservation.extent_start, extent_start); + ret =3D do_memctl_reservation(handle, XENMEM_populate_physmap, + &reservation); + if (ret < nr_extents) { + xc_error_dom_set(domid, "populate physmap"); + return (ret >=3D 0) ? -1 : ret; + } + return 0; +} + +int xc_domain_setvmxassist(int handle, unsigned int domid, int use_vmxas= sist) +{ + int ret =3D 0; +#ifdef XEN_DOMCTL_setvmxassist + DECLARE_DOMCTL(XEN_DOMCTL_setvmxassist, domid); + domctl.u.setvmxassist.use_vmxassist =3D use_vmxassist; + + ret =3D do_domctl(handle, &domctl); + if (ret) + xc_error_dom_set(domid, "setting vmxassist to %d", + use_vmxassist); +#endif + return ret; +} + +int xc_domain_max_vcpus(int handle, unsigned int domid, unsigned int max= ) +{ + int ret; + DECLARE_DOMCTL(XEN_DOMCTL_max_vcpus, domid); + domctl.u.max_vcpus.max =3D max; + + ret =3D do_domctl(handle, &domctl); + if (ret) + xc_error_dom_set(domid, "setting max vcpus to %d", max); + return ret; +} + +int xc_domain_sethandle(int handle, unsigned int domid, + xen_domain_handle_t dhandle) +{ + int ret; + DECLARE_DOMCTL(XEN_DOMCTL_setdomainhandle, domid); + memcpy(domctl.u.setdomainhandle.handle, dhandle, sizeof(xen_domain_hand= le_t)); + + ret =3D do_domctl(handle, &domctl); + if (ret) + xc_error_dom_set(domid, "set handle"); + return ret; +} + +int xc_vcpu_getinfo(int handle, unsigned int domid, unsigned int vcpu, + xc_vcpuinfo_t *info) +{ + int ret; + DECLARE_DOMCTL(XEN_DOMCTL_getvcpuinfo, domid); + domctl.u.getvcpuinfo.vcpu =3D vcpu; + + ret =3D do_domctl(handle, &domctl); + if (ret < 0) { + xc_error_dom_set(domid, "vcpu %u getinfo", vcpu); + return ret; + } + memcpy(info, &domctl.u.getvcpuinfo, sizeof(*info)); + return ret; +} + +int xc_domain_ioport_permission(int handle, unsigned int domid, + unsigned int first_port, unsigned int nr= _ports, + unsigned int allow_access) +{ + DECLARE_DOMCTL(XEN_DOMCTL_ioport_permission, domid); + domctl.u.ioport_permission.first_port =3D first_port; + domctl.u.ioport_permission.nr_ports =3D nr_ports; + domctl.u.ioport_permission.allow_access =3D allow_access; + + return do_domctl(handle, &domctl); +} + +int xc_vcpu_getcontext(int handle, unsigned int domid, + unsigned int vcpu, vcpu_guest_context_any_t *ctxt= ) +{ + int ret; + DECLARE_DOMCTL(XEN_DOMCTL_getvcpucontext, domid); + domctl.u.vcpucontext.vcpu =3D vcpu; + set_xen_guest_handle(domctl.u.vcpucontext.ctxt, ctxt); + + if (mlock(ctxt, sizeof(*ctxt)) !=3D 0) { + xc_error_set("mlock failed: %s", strerror(errno)); + return -1; + } + + ret =3D do_domctl(handle, &domctl); + if (ret) + xc_error_dom_set(domid, "vcpu %u getcontext", vcpu); + munlock(ctxt, sizeof(*ctxt)); + return ret; +} + +int xc_vcpu_setcontext(int handle, unsigned int domid, + unsigned int vcpu, vcpu_guest_context_any_t *ctxt= ) +{ + int ret; + DECLARE_DOMCTL(XEN_DOMCTL_setvcpucontext, domid); + domctl.u.vcpucontext.vcpu =3D vcpu; + set_xen_guest_handle(domctl.u.vcpucontext.ctxt, ctxt); + + if (mlock(ctxt, sizeof(*ctxt)) !=3D 0) { + xc_error_set("mlock failed: %s", strerror(errno)); + return -1; + } + + ret =3D do_domctl(handle, &domctl); + if (ret) + xc_error_dom_set(domid, "vcpu %u setcontext", vcpu); + + munlock(ctxt, sizeof(*ctxt)); + return ret; +} + +int xc_domain_irq_permission(int handle, unsigned int domid, + unsigned char pirq, unsigned char allow_acc= ess) +{ + DECLARE_DOMCTL(XEN_DOMCTL_irq_permission, domid); + domctl.u.irq_permission.pirq =3D pirq; + domctl.u.irq_permission.allow_access =3D allow_access; + int ret; + + ret =3D do_domctl(handle, &domctl); + if (ret) + xc_error_dom_set(domid, "irq permission %u to %u", + pirq, allow_access); + return ret; +} + +int xc_domain_iomem_permission(int handle, unsigned int domid, + unsigned long first_mfn, unsigned long nr= _mfns, + unsigned char allow_access) +{ + DECLARE_DOMCTL(XEN_DOMCTL_iomem_permission, domid); + domctl.u.iomem_permission.first_mfn =3D first_mfn; + domctl.u.iomem_permission.nr_mfns =3D nr_mfns; + domctl.u.iomem_permission.allow_access =3D allow_access; + int ret; + + ret =3D do_domctl(handle, &domctl); + if (ret) + xc_error_dom_set(domid, "iomem permission [%lu, %lu] to %u", + first_mfn, first_mfn + nr_mfns, allow_access); + return ret; +} + +long long xc_domain_get_cpu_usage(int handle, unsigned int domid, + unsigned int vcpu) +{ + DECLARE_DOMCTL(XEN_DOMCTL_getvcpuinfo, domid); + domctl.u.getvcpuinfo.vcpu =3D vcpu; + + if (do_domctl(handle, &domctl) < 0) { + xc_error_dom_set(domid, "get cpu %d usage", vcpu); + return -1; + } + return domctl.u.getvcpuinfo.cpu_time; +} + +void *xc_map_foreign_range(int handle, unsigned int domid, + int size, int prot, unsigned long mfn) +{ + privcmd_mmap_entry_t entry =3D { + .mfn =3D mfn, + .npages =3D (size + PAGE_SIZE - 1) >> PAGE_SHIFT, + }; + privcmd_mmap_t ioctlx =3D { + .num =3D 1, + .dom =3D domid, + .entry =3D &entry, + }; + void *addr; + + addr =3D do_mmap(NULL, size, prot, MAP_SHARED, handle, 0); + if (addr =3D=3D MAP_FAILED) { + xc_error_set("mmap failed: %s", strerror(errno)); + xc_error_dom_set(domid, "map foreign range [%lx,%lx] prot %u", + mfn, mfn + size, prot); + return NULL; + } + entry.va =3D (unsigned long) addr; + if (do_ioctl(handle, IOCTL_PRIVCMD_MMAP, &ioctlx) < 0) { + xc_error_set("ioctl failed: %s", strerror(errno)); + xc_error_dom_set(domid, "map foreign range [%lx,%lx] prot %u", + mfn, mfn + size, prot); + munmap(addr, size); + return NULL; + } + return addr; +} + +int xc_map_foreign_ranges(int handle, unsigned int domid, + privcmd_mmap_entry_t *entries, int nr) +{ + privcmd_mmap_t ioctlx =3D { + .num =3D nr, + .dom =3D domid, + .entry =3D entries, + }; + int ret; + + ret =3D do_ioctl(handle, IOCTL_PRIVCMD_MMAP, &ioctlx); + if (ret < 0) { + xc_error_set("ioctl failed: %s", strerror(errno)); + xc_error_dom_set(domid, "map foreign ranges"); + return -1; + } + return ret; +} + +int xc_readconsolering(int handle, char **pbuffer, + unsigned int *pnr_chars, int clear) +{ + int ret; + DECLARE_SYSCTL(XEN_SYSCTL_readconsole); + char *buffer =3D *pbuffer; + unsigned int nr_chars =3D *pnr_chars; + + set_xen_guest_handle(sysctl.u.readconsole.buffer, buffer); + sysctl.u.readconsole.count =3D nr_chars; + sysctl.u.readconsole.clear =3D clear; + + if (mlock(buffer, nr_chars) !=3D 0) { + xc_error_set("read console ring: mlock failed: %s", + strerror(errno)); + return -1; + } + + ret =3D do_sysctl(handle, &sysctl); + if (ret !=3D 0) + xc_error_set("read console ring failed: %s", xc_error_get()); + else + *pnr_chars =3D sysctl.u.readconsole.count; + + munlock(buffer, nr_chars); + return ret; +} + +int xc_send_debug_keys(int handle, char *keys) +{ + int ret; + DECLARE_SYSCTL(XEN_SYSCTL_debug_keys); + + set_xen_guest_handle(sysctl.u.debug_keys.keys, keys); + sysctl.u.debug_keys.nr_keys =3D strlen(keys); + + if (mlock(keys, sysctl.u.debug_keys.nr_keys) !=3D 0) { + xc_error_set("send debug keys: mlock failed: %s", + strerror(errno)); + return -1; + } + + ret =3D do_sysctl(handle, &sysctl); + if (ret !=3D 0) + xc_error_set("send debug keys: %s", xc_error_get()); + + munlock(keys, sysctl.u.debug_keys.nr_keys); + return ret; +} + +int xc_physinfo(int handle, xc_physinfo_t *put_info) +{ + DECLARE_SYSCTL(XEN_SYSCTL_physinfo); + int ret; + + ret =3D do_sysctl(handle, &sysctl); + if (ret) { + xc_error_set("physinfo failed: %s", xc_error_get()); + return ret; + } + memcpy(put_info, &sysctl.u.physinfo, sizeof(*put_info)); + return 0; +} + +int xc_pcpu_info(int handle, int max_cpus, uint64_t *info, int *nr_cpus) +{ + DECLARE_SYSCTL(XEN_SYSCTL_getcpuinfo); + int ret; + + sysctl.u.getcpuinfo.max_cpus =3D max_cpus; + set_xen_guest_handle(sysctl.u.getcpuinfo.info, info); + + if (mlock(info, sizeof(*info) * max_cpus) !=3D 0) { + xc_error_set("mlock failed: %s", strerror(errno)); + return -1; + } + + ret =3D do_sysctl(handle, &sysctl); + if (ret) + xc_error_set("pcpu info failed: %s", xc_error_get()); + else if (ret =3D=3D 0 && nr_cpus) + *nr_cpus =3D sysctl.u.getcpuinfo.nr_cpus; + munlock(info, sizeof(*info) * max_cpus); + return ret; +} + +int xc_sched_id(int handle, int *sched_id) +{ + DECLARE_SYSCTL(XEN_SYSCTL_sched_id); + int ret; + + ret =3D do_sysctl(handle, &sysctl); + if (ret) { + xc_error_set("sched id failed: %s", xc_error_get()); + return ret; + } + *sched_id =3D sysctl.u.sched_id.sched_id; + return 0; +} + +int xc_version(int handle, int cmd, void *arg) +{ + int argsize; + int ret; + DECLARE_HYPERCALL2(__HYPERVISOR_xen_version, cmd, arg); + + switch (cmd) { + case XENVER_extraversion: + argsize =3D sizeof(xen_extraversion_t); break; + case XENVER_compile_info: + argsize =3D sizeof(xen_compile_info_t); break; + case XENVER_capabilities: + argsize =3D sizeof(xen_capabilities_info_t); break; + case XENVER_changeset: + argsize =3D sizeof(xen_changeset_info_t); break; + case XENVER_platform_parameters: + argsize =3D sizeof(xen_platform_parameters_t); break; + case XENVER_version: + argsize =3D 0; break; + default: + xc_error_set("version: unknown command"); + return -1; + } + if (argsize && mlock(arg, argsize) =3D=3D -1) { + xc_error_set("version: mlock failed: %s", strerror(errno)); + return -ENOMEM; + } + + ret =3D do_xen_hypercall(handle, &hypercall); + if (ret) + xc_error_hypercall(hypercall, ret); + + if (argsize) + munlock(arg, argsize); + return ret; +} + +int xc_evtchn_alloc_unbound(int handle, unsigned int domid, + unsigned int remote_domid) +{ + struct evtchn_alloc_unbound arg =3D { + .dom =3D domid, + .remote_dom =3D remote_domid, + }; + int ret; + + ret =3D do_evtchnctl(handle, EVTCHNOP_alloc_unbound, &arg, sizeof(arg))= ; + if (ret) { + xc_error_dom_set(domid, "alloc unbound evtchn to %d", + remote_domid); + return ret; + } + return arg.port; +} + +int xc_evtchn_reset(int handle, unsigned int domid) +{ + struct evtchn_reset arg =3D { + .dom =3D domid, + }; + int ret; + + ret =3D do_evtchnctl(handle, EVTCHNOP_reset, &arg, sizeof(arg)); + if (ret) + xc_error_dom_set(domid, "reset evtchn of %d", domid); + return ret; +} + +int xc_sched_credit_domain_set(int handle, unsigned int domid, + struct xen_domctl_sched_credit *sdom) +{ + int ret; + DECLARE_DOMCTL(XEN_DOMCTL_scheduler_op, domid); + domctl.u.scheduler_op.sched_id =3D XEN_SCHEDULER_CREDIT; + domctl.u.scheduler_op.cmd =3D XEN_DOMCTL_SCHEDOP_putinfo; + domctl.u.scheduler_op.u.credit =3D *sdom; + + ret =3D do_domctl(handle, &domctl); + if (ret < 0) + xc_error_dom_set(domid, "credit scheduler domain set"); + return ret; +} + +int xc_sched_credit_domain_get(int handle, unsigned int domid, + struct xen_domctl_sched_credit *sdom) +{ + int ret; + DECLARE_DOMCTL(XEN_DOMCTL_scheduler_op, domid); + + domctl.u.scheduler_op.sched_id =3D XEN_SCHEDULER_CREDIT; + domctl.u.scheduler_op.cmd =3D XEN_DOMCTL_SCHEDOP_getinfo; + + ret =3D do_domctl(handle, &domctl); + if (ret < 0) + xc_error_dom_set(domid, "credit scheduler domain get"); + else + *sdom =3D domctl.u.scheduler_op.u.credit; + return ret; +} + +int xc_shadow_allocation_get(int handle, unsigned int domid, uint32_t *m= b) +{ + int ret; + DECLARE_DOMCTL(XEN_DOMCTL_shadow_op, domid); + + domctl.u.shadow_op.op =3D XEN_DOMCTL_SHADOW_OP_GET_ALLOCATION; + + ret =3D do_domctl(handle, &domctl); + if (ret < 0) + xc_error_dom_set(domid, "shadow allocation get"); + else + *mb =3D domctl.u.shadow_op.mb; + return ret; +} + +int xc_shadow_allocation_set(int handle, unsigned int domid, uint32_t mb= ) +{ + int ret; + DECLARE_DOMCTL(XEN_DOMCTL_shadow_op, domid); + + domctl.u.shadow_op.op =3D XEN_DOMCTL_SHADOW_OP_SET_ALLOCATION; + domctl.u.shadow_op.mb =3D mb; + + ret =3D do_domctl(handle, &domctl); + if (ret < 0) + xc_error_dom_set(domid, "shadow allocation set"); + return ret; +} + +int xc_domain_get_pfn_list(int handle, unsigned int domid, + xen_pfn_t *pfn_array, unsigned long max_pfns) +{ + int ret; + DECLARE_DOMCTL(XEN_DOMCTL_getmemlist, domid); + + domctl.u.getmemlist.max_pfns =3D max_pfns; + set_xen_guest_handle(domctl.u.getmemlist.buffer, pfn_array); + + if (mlock(pfn_array, max_pfns * sizeof(xen_pfn_t)) !=3D 0) { + xc_error_set("mlock failed: %s", strerror(errno)); + return -1; + } + + ret =3D do_domctl(handle, &domctl); + if (ret < 0) + xc_error_dom_set(domid, "get pfn list"); + + munlock(pfn_array, max_pfns * sizeof(xen_pfn_t)); + return (ret < 0) ? ret : domctl.u.getmemlist.num_pfns; +} + +#define MARSHALL_BDF(d,b,s,f) \ + (((b) & 0xff) << 16 | ((s) & 0x1f) << 11 | ((f) & 0x7) << 8) + +int xc_domain_assign_device(int handle, unsigned int domid, + int domain, int bus, int slot, int func) +{ + int ret =3D -EBADF; +#ifdef XEN_DOMCTL_assign_device + DECLARE_DOMCTL(XEN_DOMCTL_assign_device, domid); + + domctl.u.assign_device.machine_bdf =3D MARSHALL_BDF(domain, bus, slot, = func); + ret =3D do_domctl(handle, &domctl); + if (ret < 0) + xc_error_dom_set(domid, "assign device"); +#endif + return ret; +} + +int xc_domain_deassign_device(int handle, unsigned int domid, + int domain, int bus, int slot, int func) +{ + int ret =3D -EBADF; +#ifdef XEN_DOMCTL_deassign_device + DECLARE_DOMCTL(XEN_DOMCTL_deassign_device, domid); + + domctl.u.assign_device.machine_bdf =3D MARSHALL_BDF(domain, bus, slot, = func); + ret =3D do_domctl(handle, &domctl); + if (ret < 0) + xc_error_dom_set(domid, "deassign device"); +#endif + return ret; +} + +int xc_domain_test_assign_device(int handle, unsigned int domid, + int domain, int bus, int slot, int func= ) +{ + int ret =3D -EBADF; +#ifdef XEN_DOMCTL_test_assign_device + DECLARE_DOMCTL(XEN_DOMCTL_test_assign_device, domid); + domctl.u.assign_device.machine_bdf =3D MARSHALL_BDF(domain, bus, slot, = func); + + ret =3D do_domctl(handle, &domctl); + if (ret < 0) + xc_error_dom_set(domid, "test assign device"); +#endif + return ret; +} + +int xc_domain_watchdog(int handle, int id, uint32_t timeout) +{ + int ret =3D -EBADF; +#ifdef SCHEDOP_watchdog + sched_watchdog_t arg =3D { + .id =3D (uint32_t) id, + .timeout =3D timeout, + }; + DECLARE_HYPERCALL2(__HYPERVISOR_sched_op, SCHEDOP_watchdog, &arg); + + if (mlock(&arg, sizeof(arg)) !=3D 0) { + xc_error_set("mlock failed: %s", strerror(errno)); + return -1; + } + + ret =3D do_xen_hypercall(handle, &hypercall); + if (ret < 0) { + xc_error_hypercall(hypercall, ret); + } + munlock(&arg, sizeof(arg)); +#endif + return ret; +} + +int xc_domain_set_machine_address_size(int xc, uint32_t domid, unsigned = int width) +{ + DECLARE_DOMCTL(XEN_DOMCTL_set_machine_address_size, domid); + int rc; + + domctl.u.address_size.size =3D width; + rc =3D do_domctl(xc, &domctl); + if (rc !=3D 0) + xc_error_dom_set(domid, "set machine address size"); + + return rc; +} + +int xc_domain_get_machine_address_size(int xc, uint32_t domid) +{ + DECLARE_DOMCTL(XEN_DOMCTL_get_machine_address_size, domid); + int rc; + + rc =3D do_domctl(xc, &domctl); + if (rc !=3D 0) + xc_error_dom_set(domid, "get machine address size"); + return rc =3D=3D 0 ? domctl.u.address_size.size : rc; +} + +#include "xc_cpuid.h" +int xc_domain_cpuid_set(int xc, unsigned int domid, int hvm, + uint32_t input, uint32_t oinput, + char *config[4], char *config_out[4]) +{ + int ret =3D -EBADF; +#ifdef XEN_DOMCTL_set_cpuid + DECLARE_DOMCTL(XEN_DOMCTL_set_cpuid, domid); + uint32_t regs[4], polregs[4]; + int i, j; + + xc_cpuid(input, oinput, regs); + memcpy(polregs, regs, sizeof(regs)); + do_cpuid_policy(xc, domid, hvm, input, polregs); + + for (i =3D 0; i < 4; i++) { + if (!config[i]) { + regs[i] =3D polregs[i]; + continue; + } + =09 + for (j =3D 0; j < 32; j++) { + unsigned char val, polval; + + val =3D !!((regs[i] & (1U << (31 - j)))); + polval =3D !!((regs[i] & (1U << (31 - j)))); + + switch (config[i][j]) { + case '1': val =3D 1; break; /* force to true */ + case '0': val =3D 0; break; /* force to false */ + case 'x': val =3D polval; break; + case 'k': case 's': break; + default: + xc_error_dom_set(domid, "domain cpuid set: invalid config"); + ret =3D -EINVAL; + goto out; + } + + if (val) + set_bit(31 - j, regs[i]); + else + clear_bit(31 - j, regs[i]); + + if (config_out && config_out[i]) { + config_out[i][j] =3D (config[i][j] =3D=3D 's') + ? '0' + val + : config[i][j]; + } + } + } + + domctl.u.cpuid.input[0] =3D input; + domctl.u.cpuid.input[1] =3D oinput; + domctl.u.cpuid.eax =3D regs[0]; + domctl.u.cpuid.ebx =3D regs[1]; + domctl.u.cpuid.ecx =3D regs[2]; + domctl.u.cpuid.edx =3D regs[3]; + ret =3D do_domctl(xc, &domctl); + if (ret) { + xc_error_dom_set(domid, "cpuid set"); + goto out; + } +out: +#endif + return ret; +} + +int xc_domain_cpuid_apply(int xc, unsigned int domid, int hvm) +{ + int ret =3D -EBADF; +#ifdef XEN_DOMCTL_set_cpuid + uint32_t regs[4], base_max, ext_max, eax, ecx; + + /* determinate cpuid range */ + xc_cpuid(0, 0, regs); + base_max =3D MIN(regs[0], DEF_MAX_BASE); + xc_cpuid(0x80000000, 0, regs); + ext_max =3D MIN(regs[0], DEF_MAX_EXT); + + eax =3D ecx =3D 0; + while (!(eax & 0x80000000) || (eax <=3D ext_max)) { + xc_cpuid(eax, ecx, regs); + + do_cpuid_policy(xc, domid, hvm, eax, regs); + =09 + if (regs[0] || regs[1] || regs[2] || regs[3]) { + DECLARE_DOMCTL(XEN_DOMCTL_set_cpuid, domid); + =09 + domctl.u.cpuid.input[0] =3D eax; + domctl.u.cpuid.input[1] =3D (eax =3D=3D 4) ? ecx : XEN_CPUID_INPUT_UN= USED; + domctl.u.cpuid.eax =3D regs[0]; + domctl.u.cpuid.ebx =3D regs[1]; + domctl.u.cpuid.ecx =3D regs[2]; + domctl.u.cpuid.edx =3D regs[3]; + + ret =3D do_domctl(xc, &domctl); + if (ret) { + xc_error_dom_set(domid, "cpuid apply"); + goto out; + } + + /* we repeat when doing node 4 (cache descriptor leaves) increasing e= cx=20 + * until the cpuid eax value masked is 0 */ + if (eax =3D=3D 4) { + ecx++; + if ((regs[0] & 0x1f) !=3D 0) + continue; + ecx =3D 0; + } + } + + eax++; + if (!(eax & 0x80000000) && (eax > base_max)) + eax =3D 0x80000000; + } + ret =3D 0; +out: +#endif + return ret; +} + +/* + * return 1 on checking success=20 + * 0 on checking failure + * -EINVAL if the config contains unknown character + */ +int xc_cpuid_check(uint32_t input, uint32_t optsubinput, + char *config[4], char *config_out[4]) +{ + int ret =3D -EBADF; +#ifdef XEN_DOMCTL_set_cpuid + uint32_t regs[4]; + int i, j; + + xc_cpuid(input, optsubinput, regs); + + ret =3D 1; + for (i =3D 0; i < 4; i++) { + if (!config[i]) + continue; + for (j =3D 0; j < 32; j++) { + unsigned char val; + + val =3D !!((regs[i] & (1U << (31 - j)))); + + switch (config[i][j]) { + case '1': if (!val) { ret =3D 0; goto out; }; break; + case '0': if (val) { ret =3D 0; goto out; }; break; + case 'x': case 's': break; + default: + xc_error_set("cpuid check: invalid config"); + ret =3D -EINVAL; + goto out; + } + + if (config_out && config_out[i]) { + config_out[i][j] =3D (config[i][j] =3D=3D 's') + ? '0' + val + : config[i][j]; + } + } + }=20 +out: +#endif + return ret; +} + +#ifndef HVM_PARAM_HPET_ENABLED +#define HVM_PARAM_HPET_ENABLED 11 +#endif + +#ifndef HVM_PARAM_ACPI_S_STATE +#define HVM_PARAM_ACPI_S_STATE 14 +#endif + +#ifndef HVM_PARAM_VPT_ALIGN +#define HVM_PARAM_VPT_ALIGN 16 +#endif + +int xc_domain_send_s3resume(int handle, unsigned int domid) +{ + return xc_set_hvm_param(handle, domid, HVM_PARAM_ACPI_S_STATE, 0); +} + +int xc_domain_set_timer_mode(int handle, unsigned int domid, int mode) +{ + return xc_set_hvm_param(handle, domid, + HVM_PARAM_TIMER_MODE, (unsigned long) mode); +} + +int xc_domain_set_hpet(int handle, unsigned int domid, int hpet) +{ + return xc_set_hvm_param(handle, domid, HVM_PARAM_HPET_ENABLED, (unsigne= d long) hpet); +} + +int xc_domain_set_vpt_align(int handle, unsigned int domid, int vpt_alig= n) +{ + return xc_set_hvm_param(handle, domid, HVM_PARAM_HPET_ENABLED, (unsigne= d long) vpt_align); +} + +int xc_domain_get_acpi_s_state(int handle, unsigned int domid) +{ + int ret; + unsigned long value; + + ret =3D xc_get_hvm_param(handle, domid, HVM_PARAM_ACPI_S_STATE, &value)= ; + if (ret !=3D 0) + xc_error_dom_set(domid, "get acpi s-state"); + return value; +} diff --git a/tools/ocaml/libs/xc/xc_stubs.c b/tools/ocaml/libs/xc/xc_stub= s.c new file mode 100644 index 0000000..b43a750 --- /dev/null +++ b/tools/ocaml/libs/xc/xc_stubs.c @@ -0,0 +1,1170 @@ +/* + * Copyright (C) 2006-2007 XenSource Ltd. + * Copyright (C) 2008 Citrix Ltd. + * Author Vincent Hanquez + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as publis= hed + * 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. + */ + +#define _XOPEN_SOURCE 600 +#include + +#define CAML_NAME_SPACE +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "xc.h" + +#include "mmap_stubs.h" + +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE-1)) + +#define _H(__h) (Int_val(__h)) +#define _D(__d) ((uint32_t)Int_val(__d)) + +#define Val_none (Val_int(0)) + +#define string_of_option_array(array, index) \ + ((Field(array, index) =3D=3D Val_none) ? NULL : String_val(Field(Field(= array, index), 0))) + +/* maybe here we should check the range of the input instead of blindly + * casting it to uint32 */ +#define cpuid_input_of_val(i1, i2, input) \ + i1 =3D (uint32_t) Int64_val(Field(input, 0)); \ + i2 =3D ((Field(input, 1) =3D=3D Val_none) ? 0xffffffff : (uint32_t) Int= 64_val(Field(Field(input, 1), 0))); + +/** + * Convert the given number of pages to an amount in MiB, rounded up. + */ +void failwith_xc(void) +{ + caml_raise_with_string(*caml_named_value("xc.error"), xc_error_get()); +} + +CAMLprim value stub_sizeof_core_header(value unit) +{ + CAMLparam1(unit); + CAMLreturn(Val_int(sizeof(struct xc_core_header))); +} + +CAMLprim value stub_sizeof_vcpu_guest_context(value unit) +{ + CAMLparam1(unit); + CAMLreturn(Val_int(sizeof(struct vcpu_guest_context))); +} + +CAMLprim value stub_sizeof_xen_pfn(value unit) +{ + CAMLparam1(unit); + CAMLreturn(Val_int(sizeof(xen_pfn_t))); +} + +#define XC_CORE_MAGIC 0xF00FEBED +#define XC_CORE_MAGIC_HVM 0xF00FEBEE + +CAMLprim value stub_marshall_core_header(value header) +{ + CAMLparam1(header); + CAMLlocal1(s); + struct xc_core_header c_header; + + c_header.xch_magic =3D (Field(header, 0)) + ? XC_CORE_MAGIC + : XC_CORE_MAGIC_HVM; + c_header.xch_nr_vcpus =3D Int_val(Field(header, 1)); + c_header.xch_nr_pages =3D Nativeint_val(Field(header, 2)); + c_header.xch_ctxt_offset =3D Int64_val(Field(header, 3)); + c_header.xch_index_offset =3D Int64_val(Field(header, 4)); + c_header.xch_pages_offset =3D Int64_val(Field(header, 5)); + + s =3D caml_alloc_string(sizeof(c_header)); + memcpy(String_val(s), (char *) &c_header, sizeof(c_header)); + CAMLreturn(s); +} + +CAMLprim value stub_xc_interface_open() +{ + int handle; + handle =3D xc_interface_open(); + if (handle =3D=3D -1) + failwith_xc(); + return Val_int(handle); +} + + +CAMLprim value stub_xc_interface_open_fake() +{ + return Val_int(-1); +} + +CAMLprim value stub_xc_using_injection() +{ + if (xc_using_injection ()){ + return Val_int(1); + } else { + return Val_int(0); + } +} + +CAMLprim value stub_xc_interface_close(value xc_handle) +{ + CAMLparam1(xc_handle); + + int handle =3D _H(xc_handle); + // caml_enter_blocking_section(); + xc_interface_close(handle); + // caml_leave_blocking_section(); + + CAMLreturn(Val_unit); +} + +static int domain_create_flag_table[] =3D { + XEN_DOMCTL_CDF_hvm_guest, + XEN_DOMCTL_CDF_hap, +}; + +CAMLprim value stub_xc_domain_create(value xc_handle, value ssidref, + value flags, value handle) +{ + CAMLparam4(xc_handle, ssidref, flags, handle); + + uint32_t domid =3D 0; + xen_domain_handle_t h =3D { 0 }; + int result; + int i; + int c_xc_handle =3D _H(xc_handle); + uint32_t c_ssidref =3D Int32_val(ssidref); + unsigned int c_flags =3D 0; + value l; + + if (Wosize_val(handle) !=3D 16) + caml_invalid_argument("Handle not a 16-integer array"); + + for (i =3D 0; i < sizeof(h); i++) { + h[i] =3D Int_val(Field(handle, i)) & 0xff; + } + + for (l =3D flags; l !=3D Val_none; l =3D Field(l, 1)) { + int v =3D Int_val(Field(l, 0)); + c_flags |=3D domain_create_flag_table[v]; + } + + // caml_enter_blocking_section(); + result =3D xc_domain_create(c_xc_handle, c_ssidref, h, c_flags, &domid)= ; + // caml_leave_blocking_section(); + + if (result < 0) + failwith_xc(); + + CAMLreturn(Val_int(domid)); +} + +CAMLprim value stub_xc_domain_setvmxassist(value xc_handle, value domid, + value use_vmxassist) +{ + CAMLparam3(xc_handle, domid, use_vmxassist); + int r; + + r =3D xc_domain_setvmxassist(_H(xc_handle), _D(domid), + Bool_val(use_vmxassist)); + if (r) + failwith_xc(); + + CAMLreturn(Val_unit); +} + +CAMLprim value stub_xc_domain_max_vcpus(value xc_handle, value domid, + value max_vcpus) +{ + CAMLparam3(xc_handle, domid, max_vcpus); + int r; + + r =3D xc_domain_max_vcpus(_H(xc_handle), _D(domid), Int_val(max_vcpus))= ; + if (r) + failwith_xc(); + + CAMLreturn(Val_unit); +} + + +value stub_xc_domain_sethandle(value xc_handle, value domid, value handl= e) +{ + CAMLparam3(xc_handle, domid, handle); + xen_domain_handle_t h =3D { 0 }; + int i; + + if (Wosize_val(handle) !=3D 16) + caml_invalid_argument("Handle not a 16-integer array"); + + for (i =3D 0; i < sizeof(h); i++) { + h[i] =3D Int_val(Field(handle, i)) & 0xff; + } + + i =3D xc_domain_sethandle(_H(xc_handle), _D(domid), h); + if (i) + failwith_xc(); + + CAMLreturn(Val_unit); +} + +static value dom_op(value xc_handle, value domid, int (*fn)(int, uint32_= t)) +{ + CAMLparam2(xc_handle, domid); + + int c_xc_handle =3D _H(xc_handle); + uint32_t c_domid =3D _D(domid); + + // caml_enter_blocking_section(); + int result =3D fn(c_xc_handle, c_domid); + // caml_leave_blocking_section(); + if (result) + failwith_xc(); + CAMLreturn(Val_unit); +} + +CAMLprim value stub_xc_domain_pause(value xc_handle, value domid) +{ + return dom_op(xc_handle, domid, xc_domain_pause); +} + + +CAMLprim value stub_xc_domain_unpause(value xc_handle, value domid) +{ + return dom_op(xc_handle, domid, xc_domain_unpause); +} + +CAMLprim value stub_xc_domain_destroy(value xc_handle, value domid) +{ + return dom_op(xc_handle, domid, xc_domain_destroy); +} + +CAMLprim value stub_xc_domain_resume_fast(value xc_handle, value domid) +{ + return dom_op(xc_handle, domid, xc_domain_resume_fast); +} + +CAMLprim value stub_xc_domain_shutdown(value handle, value domid, value = reason) +{ + CAMLparam3(handle, domid, reason); + int ret; + + ret =3D xc_domain_shutdown(_H(handle), _D(domid), Int_val(reason)); + if (ret < 0) + failwith_xc(); + + CAMLreturn(Val_unit); +} + +static value alloc_domaininfo(xc_domaininfo_t * info) +{ + CAMLparam0(); + CAMLlocal2(result, tmp); + int i; + + result =3D caml_alloc_tuple(16); + + Store_field(result, 0, Val_int(info->domain)); + Store_field(result, 1, Val_bool(info->flags & XEN_DOMINF_dying)); + Store_field(result, 2, Val_bool(info->flags & XEN_DOMINF_shutdown)); + Store_field(result, 3, Val_bool(info->flags & XEN_DOMINF_paused)); + Store_field(result, 4, Val_bool(info->flags & XEN_DOMINF_blocked)); + Store_field(result, 5, Val_bool(info->flags & XEN_DOMINF_running)); + Store_field(result, 6, Val_bool(info->flags & XEN_DOMINF_hvm_guest)); + Store_field(result, 7, Val_int((info->flags >> XEN_DOMINF_shutdownshif= t) + & XEN_DOMINF_shutdownmask)); + Store_field(result, 8, caml_copy_nativeint(info->tot_pages)); + Store_field(result, 9, caml_copy_nativeint(info->max_pages)); + Store_field(result, 10, caml_copy_int64(info->shared_info_frame)); + Store_field(result, 11, caml_copy_int64(info->cpu_time)); + Store_field(result, 12, Val_int(info->nr_online_vcpus)); + Store_field(result, 13, Val_int(info->max_vcpu_id)); + Store_field(result, 14, caml_copy_int32(info->ssidref)); + + tmp =3D caml_alloc_small(16, 0); + for (i =3D 0; i < 16; i++) { + Field(tmp, i) =3D Val_int(info->handle[i]); + } + + Store_field(result, 15, tmp); + + CAMLreturn(result); +} + +CAMLprim value stub_xc_domain_getinfolist(value xc_handle, value first_d= omain, value nb) +{ + CAMLparam3(xc_handle, first_domain, nb); + CAMLlocal2(result, temp); + xc_domaininfo_t * info; + int i, ret, toalloc; + + /* get the minimum number of allocate byte we need and bump it up to pa= ge boundary */ + toalloc =3D (sizeof(xc_domaininfo_t) * Int_val(nb)) | 0xfff; + ret =3D posix_memalign((void **) ((void *) &info), 4096, toalloc); + if (ret) + caml_raise_out_of_memory(); + + result =3D temp =3D Val_emptylist; + + int c_xc_handle =3D _H(xc_handle); + uint32_t c_first_domain =3D _D(first_domain); + unsigned int c_max_domains =3D Int_val(nb); + // caml_enter_blocking_section(); + int retval =3D xc_domain_getinfolist(c_xc_handle, c_first_domain, + c_max_domains, info); + // caml_leave_blocking_section(); + + if (retval < 0) { + free(info); + failwith_xc(); + } + for (i =3D 0; i < retval; i++) { + result =3D caml_alloc_small(2, Tag_cons); + Field(result, 0) =3D Val_int(0); + Field(result, 1) =3D temp; + temp =3D result; + + Store_field(result, 0, alloc_domaininfo(info + i)); + } + + free(info); + CAMLreturn(result); +} + +CAMLprim value stub_xc_domain_getinfo(value xc_handle, value domid) +{ + CAMLparam2(xc_handle, domid); + CAMLlocal1(result); + xc_domaininfo_t info; + int ret; + + ret =3D xc_domain_getinfo(_H(xc_handle), _D(domid), &info); + if (ret !=3D 0) + failwith_xc(); + + result =3D alloc_domaininfo(&info); + CAMLreturn(result); +} + +CAMLprim value stub_xc_vcpu_getinfo(value xc_handle, value domid, value = vcpu) +{ + CAMLparam3(xc_handle, domid, vcpu); + CAMLlocal1(result); + xc_vcpuinfo_t info; + int retval; + + int c_xc_handle =3D _H(xc_handle); + uint32_t c_domid =3D _D(domid); + uint32_t c_vcpu =3D Int_val(vcpu); + // caml_enter_blocking_section(); + retval =3D xc_vcpu_getinfo(c_xc_handle, c_domid, + c_vcpu, &info); + // caml_leave_blocking_section(); + if (retval < 0) + failwith_xc(); + + result =3D caml_alloc_tuple(5); + Store_field(result, 0, Val_bool(info.online)); + Store_field(result, 1, Val_bool(info.blocked)); + Store_field(result, 2, Val_bool(info.running)); + Store_field(result, 3, caml_copy_int64(info.cpu_time)); + Store_field(result, 4, caml_copy_int32(info.cpu)); + + CAMLreturn(result); +} + +CAMLprim value stub_xc_vcpu_context_get(value xc_handle, value domid, + value cpu) +{ + CAMLparam3(xc_handle, domid, cpu); + CAMLlocal1(context); + int ret; + struct vcpu_guest_context ctxt; + + ret =3D xc_vcpu_getcontext(_H(xc_handle), _D(domid), Int_val(cpu), &ctx= t); + + context =3D caml_alloc_string(sizeof(ctxt)); + memcpy(String_val(context), (char *) &ctxt, sizeof(ctxt)); + + CAMLreturn(context); +} + +CAMLprim value stub_xc_vcpu_setaffinity(value xc_handle, value domid, + value vcpu, value cpumap) +{ + CAMLparam4(xc_handle, domid, vcpu, cpumap); + uint64_t c_cpumap; + int retval; + + c_cpumap =3D Int64_val(cpumap); + retval =3D xc_vcpu_setaffinity(_H(xc_handle), _D(domid), + Int_val(vcpu), c_cpumap); + if (retval < 0) + failwith_xc(); + CAMLreturn(Val_unit); +} + +CAMLprim value stub_xc_vcpu_getaffinity(value xc_handle, value domid, + value vcpu) +{ + CAMLparam3(xc_handle, domid, vcpu); + CAMLlocal1(ret); + uint64_t cpumap; + int retval; + + retval =3D xc_vcpu_getaffinity(_H(xc_handle), _D(domid), + Int_val(vcpu), &cpumap); + if (retval < 0) + failwith_xc(); + ret =3D caml_copy_int64(cpumap); + CAMLreturn(ret); +} + +CAMLprim value stub_xc_sched_id(value xc_handle) +{ + CAMLparam1(xc_handle); + int sched_id; + + if (xc_sched_id(_H(xc_handle), &sched_id)) + failwith_xc(); + CAMLreturn(Val_int(sched_id)); +} + +CAMLprim value stub_xc_evtchn_alloc_unbound(value xc_handle, + value local_domid, + value remote_domid) +{ + CAMLparam3(xc_handle, local_domid, remote_domid); + + int c_xc_handle =3D _H(xc_handle); + uint32_t c_local_domid =3D _D(local_domid); + uint32_t c_remote_domid =3D _D(remote_domid); + + // caml_enter_blocking_section(); + int result =3D xc_evtchn_alloc_unbound(c_xc_handle, c_local_domid, + c_remote_domid); + // caml_leave_blocking_section(); + + if (result < 0) + failwith_xc(); + CAMLreturn(Val_int(result)); +} + +CAMLprim value stub_xc_evtchn_reset(value handle, value domid) +{ + CAMLparam2(handle, domid); + int r; + + r =3D xc_evtchn_reset(_H(handle), _D(domid)); + if (r < 0) + failwith_xc(); + CAMLreturn(Val_unit); +} + + +#define RING_SIZE 32768 +static char ring[RING_SIZE]; + +CAMLprim value stub_xc_readconsolering(value xc_handle) +{ + unsigned int size =3D RING_SIZE; + char *ring_ptr =3D ring; + + CAMLparam1(xc_handle); + int c_xc_handle =3D _H(xc_handle); + + // caml_enter_blocking_section(); + int retval =3D xc_readconsolering(c_xc_handle, &ring_ptr, &size, 0); + // caml_leave_blocking_section(); + + if (retval) + failwith_xc(); + ring[size] =3D '\0'; + CAMLreturn(caml_copy_string(ring)); +} + +CAMLprim value stub_xc_send_debug_keys(value xc_handle, value keys) +{ + CAMLparam2(xc_handle, keys); + int r; + + r =3D xc_send_debug_keys(_H(xc_handle), String_val(keys)); + if (r) + failwith_xc(); + CAMLreturn(Val_unit); +} + +CAMLprim value stub_xc_physinfo(value xc_handle) +{ + CAMLparam1(xc_handle); + CAMLlocal3(physinfo, cap_list, tmp); + xc_physinfo_t c_physinfo; + int r; + + // caml_enter_blocking_section(); + r =3D xc_physinfo(_H(xc_handle), &c_physinfo); + // caml_leave_blocking_section(); + + if (r) + failwith_xc(); + + tmp =3D cap_list =3D Val_emptylist; + for (r =3D 0; r < 2; r++) { + if ((c_physinfo.capabilities >> r) & 1) { + tmp =3D caml_alloc_small(2, Tag_cons); + Field(tmp, 0) =3D Val_int(r); + Field(tmp, 1) =3D cap_list; + cap_list =3D tmp; + } + } + + physinfo =3D caml_alloc_tuple(9); + Store_field(physinfo, 0, Val_int(c_physinfo.threads_per_core)); + Store_field(physinfo, 1, Val_int(c_physinfo.cores_per_socket)); + Store_field(physinfo, 2, Val_int(c_physinfo.nr_cpus)); + Store_field(physinfo, 3, Val_int(c_physinfo.max_node_id)); + Store_field(physinfo, 4, Val_int(c_physinfo.cpu_khz)); + Store_field(physinfo, 5, caml_copy_nativeint(c_physinfo.total_pages)); + Store_field(physinfo, 6, caml_copy_nativeint(c_physinfo.free_pages)); + Store_field(physinfo, 7, caml_copy_nativeint(c_physinfo.scrub_pages)); + Store_field(physinfo, 8, cap_list); + + CAMLreturn(physinfo); +} + +CAMLprim value stub_xc_pcpu_info(value xc_handle, value nr_cpus) +{ + CAMLparam2(xc_handle, nr_cpus); + CAMLlocal2(pcpus, v); + uint64_t *info; + int r, size; + + if (Int_val(nr_cpus) < 1) + caml_invalid_argument("nr_cpus"); +=09 + info =3D calloc(Int_val(nr_cpus) + 1, sizeof(uint64_t)); + if (!info) + caml_raise_out_of_memory(); + + // caml_enter_blocking_section(); + r =3D xc_pcpu_info(_H(xc_handle), Int_val(nr_cpus), info, &size); + // caml_leave_blocking_section(); + + if (r) { + free(info); + failwith_xc(); + } + + if (size > 0) { + int i; + pcpus =3D caml_alloc(size, 0); + for (i =3D 0; i < size; i++) { + v =3D caml_copy_int64(info[i]); + caml_modify(&Field(pcpus, i), v); + } + } else + pcpus =3D Atom(0); + free(info); + CAMLreturn(pcpus); +} + +CAMLprim value stub_xc_domain_setmaxmem(value xc_handle, value domid, + value max_memkb) +{ + CAMLparam3(xc_handle, domid, max_memkb); + + int c_xc_handle =3D _H(xc_handle); + uint32_t c_domid =3D _D(domid); + unsigned int c_max_memkb =3D Int64_val(max_memkb); + // caml_enter_blocking_section(); + int retval =3D xc_domain_setmaxmem(c_xc_handle, c_domid, + c_max_memkb); + // caml_leave_blocking_section(); + if (retval) + failwith_xc(); + CAMLreturn(Val_unit); +} + +CAMLprim value stub_xc_domain_set_memmap_limit(value xc_handle, value do= mid, + value map_limitkb) +{ + CAMLparam3(xc_handle, domid, map_limitkb); + unsigned long v; + int retval; + + v =3D Int64_val(map_limitkb); + retval =3D xc_domain_set_memmap_limit(_H(xc_handle), _D(domid), v); + if (retval) + failwith_xc(); + + CAMLreturn(Val_unit); +} + +CAMLprim value stub_xc_domain_memory_increase_reservation(value xc_handl= e, + value domid, + value mem_kb) +{ + CAMLparam3(xc_handle, domid, mem_kb); + + unsigned long nr_extents =3D ((unsigned long)(Int64_val(mem_kb))) >> (P= AGE_SHIFT - 10); + + int c_xc_handle =3D _H(xc_handle); + uint32_t c_domid =3D _D(domid); + // caml_enter_blocking_section(); + int retval =3D xc_domain_memory_increase_reservation(c_xc_handle, c_dom= id, + nr_extents, 0, 0, NU= LL); + // caml_leave_blocking_section(); + + if (retval) + failwith_xc(); + CAMLreturn(Val_unit); +} + +CAMLprim value stub_xc_domain_set_machine_address_size(value xc_handle, + value domid, + value width) +{ + CAMLparam3(xc_handle, domid, width); + int c_xc_handle =3D _H(xc_handle); + uint32_t c_domid =3D _D(domid); + int c_width =3D Int_val(width); + + int retval =3D xc_domain_set_machine_address_size(c_xc_handle, c_domid,= c_width); + if (retval) + failwith_xc(); + CAMLreturn(Val_unit); +} + +CAMLprim value stub_xc_domain_get_machine_address_size(value xc_handle, + value domid) +{ + CAMLparam2(xc_handle, domid); + int retval; + + retval =3D xc_domain_get_machine_address_size(_H(xc_handle), _D(domid))= ; + if (retval < 0) + failwith_xc(); + CAMLreturn(Val_int(retval)); +} + +CAMLprim value stub_xc_domain_cpuid_set(value xc_handle, value domid, + value is_hvm, value input, + value config) +{ + CAMLparam5(xc_handle, domid, is_hvm, input, config); + CAMLlocal2(array, tmp); + int r; + char *c_config[4], *out_config[4]; + uint32_t c_input, c_oinput; + + c_config[0] =3D string_of_option_array(config, 0); + c_config[1] =3D string_of_option_array(config, 1); + c_config[2] =3D string_of_option_array(config, 2); + c_config[3] =3D string_of_option_array(config, 3); + + cpuid_input_of_val(c_input, c_oinput, input); + + array =3D caml_alloc(4, 0); + for (r =3D 0; r < 4; r++) { + tmp =3D Val_none; + if (c_config[r]) { + tmp =3D caml_alloc_small(1, 0); + Field(tmp, 0) =3D caml_alloc_string(32); + } + Store_field(array, r, tmp); + } + + for (r =3D 0; r < 4; r++) + out_config[r] =3D (c_config[r]) ? String_val(Field(Field(array, r), 0)= ) : NULL; + + r =3D xc_domain_cpuid_set(_H(xc_handle), _D(domid), Bool_val(is_hvm), + c_input, c_oinput, c_config, out_config); + if (r < 0) + failwith_xc(); + CAMLreturn(array); +} + +CAMLprim value stub_xc_domain_cpuid_apply(value xc_handle, value domid, = value is_hvm) +{ + CAMLparam3(xc_handle, domid, is_hvm); + int r; + r =3D xc_domain_cpuid_apply(_H(xc_handle), _D(domid), Bool_val(is_hvm))= ; + if (r < 0) + failwith_xc(); + CAMLreturn(Val_unit); +} + +CAMLprim value stub_xc_cpuid_check(value input, value config) +{ + CAMLparam2(input, config); + CAMLlocal3(ret, array, tmp); + int r; + uint32_t c_input, c_oinput; + char *c_config[4], *out_config[4]; + + c_config[0] =3D string_of_option_array(config, 0); + c_config[1] =3D string_of_option_array(config, 1); + c_config[2] =3D string_of_option_array(config, 2); + c_config[3] =3D string_of_option_array(config, 3); + + cpuid_input_of_val(c_input, c_oinput, input); + + array =3D caml_alloc(4, 0); + for (r =3D 0; r < 4; r++) { + tmp =3D Val_none; + if (c_config[r]) { + tmp =3D caml_alloc_small(1, 0); + Field(tmp, 0) =3D caml_alloc_string(32); + } + Store_field(array, r, tmp); + } + + for (r =3D 0; r < 4; r++) + out_config[r] =3D (c_config[r]) ? String_val(Field(Field(array, r), 0)= ) : NULL; + + r =3D xc_cpuid_check(c_input, c_oinput, c_config, out_config); + if (r < 0) + failwith_xc(); + + ret =3D caml_alloc_tuple(2); + Store_field(ret, 0, Val_bool(r)); + Store_field(ret, 1, array); + + CAMLreturn(ret); +} + +CAMLprim value stub_xc_version_version(value xc_handle) +{ + CAMLparam1(xc_handle); + CAMLlocal1(result); + xen_extraversion_t extra; + long packed; + int retval; + + int c_xc_handle =3D _H(xc_handle); + // caml_enter_blocking_section(); + packed =3D xc_version(c_xc_handle, XENVER_version, NULL); + retval =3D xc_version(c_xc_handle, XENVER_extraversion, &extra); + // caml_leave_blocking_section(); + + if (retval) + failwith_xc(); + + result =3D caml_alloc_tuple(3); + + Store_field(result, 0, Val_int(packed >> 16)); + Store_field(result, 1, Val_int(packed & 0xffff)); + Store_field(result, 2, caml_copy_string(extra)); + + CAMLreturn(result); +} + + +CAMLprim value stub_xc_version_compile_info(value xc_handle) +{ + CAMLparam1(xc_handle); + CAMLlocal1(result); + xen_compile_info_t ci; + int retval; + + int c_xc_handle =3D _H(xc_handle); + // caml_enter_blocking_section(); + retval =3D xc_version(c_xc_handle, XENVER_compile_info, &ci); + // caml_leave_blocking_section(); + + if (retval) + failwith_xc(); + + result =3D caml_alloc_tuple(4); + + Store_field(result, 0, caml_copy_string(ci.compiler)); + Store_field(result, 1, caml_copy_string(ci.compile_by)); + Store_field(result, 2, caml_copy_string(ci.compile_domain)); + Store_field(result, 3, caml_copy_string(ci.compile_date)); + + CAMLreturn(result); +} + + +static value xc_version_single_string(value xc_handle, int code, void *i= nfo) +{ + CAMLparam1(xc_handle); + int retval; + + int c_xc_handle =3D _H(xc_handle); + // caml_enter_blocking_section(); + retval =3D xc_version(c_xc_handle, code, info); + // caml_leave_blocking_section(); + + if (retval) + failwith_xc(); + + CAMLreturn(caml_copy_string((char *)info)); +} + + +CAMLprim value stub_xc_version_changeset(value xc_handle) +{ + xen_changeset_info_t ci; + + return xc_version_single_string(xc_handle, XENVER_changeset, &ci); +} + + +CAMLprim value stub_xc_version_capabilities(value xc_handle) +{ + xen_capabilities_info_t ci; + + return xc_version_single_string(xc_handle, XENVER_capabilities, &ci); +} + + +CAMLprim value stub_pages_to_kib(value pages) +{ + CAMLparam1(pages); + + CAMLreturn(caml_copy_int64(Int64_val(pages) << (PAGE_SHIFT - 10))); +} + + +CAMLprim value stub_map_foreign_range(value xc_handle, value dom, + value size, value mfn) +{ + CAMLparam4(xc_handle, dom, size, mfn); + CAMLlocal1(result); + struct mmap_interface *intf; + + result =3D caml_alloc(sizeof(struct mmap_interface), Abstract_tag); + intf =3D (struct mmap_interface *) result; + + intf->len =3D Int_val(size); + + int c_xc_handle =3D _H(xc_handle); + uint32_t c_dom =3D _D(dom); + unsigned long c_mfn =3D Nativeint_val(mfn); + // caml_enter_blocking_section(); + intf->addr =3D xc_map_foreign_range(c_xc_handle, c_dom, + intf->len, PROT_READ|PROT_WRITE, + c_mfn); + // caml_leave_blocking_section(); + if (!intf->addr) + caml_failwith("xc_map_foreign_range error"); + CAMLreturn(result); +} + +CAMLprim value stub_sched_credit_domain_get(value xc_handle, value domid= ) +{ + CAMLparam2(xc_handle, domid); + CAMLlocal1(sdom); + struct xen_domctl_sched_credit c_sdom; + int ret; + + // caml_enter_blocking_section(); + ret =3D xc_sched_credit_domain_get(_H(xc_handle), _D(domid), &c_sdom); + // caml_leave_blocking_section(); + if (ret !=3D 0) + failwith_xc(); + + sdom =3D caml_alloc_tuple(2); + Store_field(sdom, 0, Val_int(c_sdom.weight)); + Store_field(sdom, 1, Val_int(c_sdom.cap)); + + CAMLreturn(sdom); +} + +CAMLprim value stub_sched_credit_domain_set(value xc_handle, value domid= , + value sdom) +{ + CAMLparam3(xc_handle, domid, sdom); + struct xen_domctl_sched_credit c_sdom; + int ret; + + c_sdom.weight =3D Int_val(Field(sdom, 0)); + c_sdom.cap =3D Int_val(Field(sdom, 1)); + // caml_enter_blocking_section(); + ret =3D xc_sched_credit_domain_set(_H(xc_handle), _D(domid), &c_sdom); + // caml_leave_blocking_section(); + if (ret !=3D 0) + failwith_xc(); + + CAMLreturn(Val_unit); +} + +CAMLprim value stub_shadow_allocation_get(value xc_handle, value domid) +{ + CAMLparam2(xc_handle, domid); + CAMLlocal1(mb); + uint32_t c_mb; + int ret; + + // caml_enter_blocking_section(); + ret =3D xc_shadow_allocation_get(_H(xc_handle), _D(domid), &c_mb); + // caml_leave_blocking_section(); + if (ret !=3D 0) + failwith_xc(); + + mb =3D Val_int(c_mb); + CAMLreturn(mb); +} + +CAMLprim value stub_shadow_allocation_set(value xc_handle, value domid, + value mb) +{ + CAMLparam3(xc_handle, domid, mb); + uint32_t c_mb; + int ret; + + c_mb =3D Int_val(mb); + // caml_enter_blocking_section(); + ret =3D xc_shadow_allocation_set(_H(xc_handle), _D(domid), c_mb); + // caml_leave_blocking_section(); + if (ret !=3D 0) + failwith_xc(); + + CAMLreturn(Val_unit); +} + +CAMLprim value stub_xc_domain_get_pfn_list(value xc_handle, value domid, + value nr_pfns) +{ + CAMLparam3(xc_handle, domid, nr_pfns); + CAMLlocal2(array, v); + unsigned long c_nr_pfns; + long ret, i; + xen_pfn_t *c_array; + + c_nr_pfns =3D Nativeint_val(nr_pfns); + + c_array =3D malloc(sizeof(xen_pfn_t) * c_nr_pfns); + if (!c_array) + caml_raise_out_of_memory(); + + ret =3D xc_domain_get_pfn_list(_H(xc_handle), _D(domid), + c_array, c_nr_pfns); + if (ret < 0) { + free(c_array); + failwith_xc(); + } + + array =3D caml_alloc(ret, 0); + for (i =3D 0; i < ret; i++) { + v =3D caml_copy_nativeint(c_array[i]); + Store_field(array, i, v); + } + free(c_array); + + CAMLreturn(array); +} + +CAMLprim value stub_xc_domain_ioport_permission(value xc_handle, value d= omid, + value start_port, value nr_ports, + value allow) +{ + CAMLparam5(xc_handle, domid, start_port, nr_ports, allow); + uint32_t c_start_port, c_nr_ports; + uint8_t c_allow; + int ret; + + c_start_port =3D Int_val(start_port); + c_nr_ports =3D Int_val(nr_ports); + c_allow =3D Bool_val(allow); + + ret =3D xc_domain_ioport_permission(_H(xc_handle), _D(domid), + c_start_port, c_nr_ports, c_allow); + if (ret < 0) + failwith_xc(); + + CAMLreturn(Val_unit); +} + +CAMLprim value stub_xc_domain_iomem_permission(value xc_handle, value do= mid, + value start_pfn, value nr_pfns, + value allow) +{ + CAMLparam5(xc_handle, domid, start_pfn, nr_pfns, allow); + unsigned long c_start_pfn, c_nr_pfns; + uint8_t c_allow; + int ret; + + c_start_pfn =3D Nativeint_val(start_pfn); + c_nr_pfns =3D Nativeint_val(nr_pfns); + c_allow =3D Bool_val(allow); + + ret =3D xc_domain_iomem_permission(_H(xc_handle), _D(domid), + c_start_pfn, c_nr_pfns, c_allow); + if (ret < 0) + failwith_xc(); + + CAMLreturn(Val_unit); +} + +CAMLprim value stub_xc_domain_irq_permission(value xc_handle, value domi= d, + value pirq, value allow) +{ + CAMLparam4(xc_handle, domid, pirq, allow); + uint8_t c_pirq; + uint8_t c_allow; + int ret; + + c_pirq =3D Int_val(pirq); + c_allow =3D Bool_val(allow); + + ret =3D xc_domain_irq_permission(_H(xc_handle), _D(domid), + c_pirq, c_allow); + if (ret < 0) + failwith_xc(); + + CAMLreturn(Val_unit); +} + +CAMLprim value stub_xc_hvm_check_pvdriver(value xc_handle, value domid) +{ + CAMLparam2(xc_handle, domid); + int ret; + + ret =3D xc_hvm_check_pvdriver(_H(xc_handle), _D(domid)); + if (ret < 0) + failwith_xc(); + CAMLreturn(Val_bool(ret)); +} + +CAMLprim value stub_xc_domain_test_assign_device(value xc_handle, value = domid, value desc) +{ + CAMLparam3(xc_handle, domid, desc); + int ret; + int domain, bus, slot, func; + + domain =3D Int_val(Field(desc, 0)); + bus =3D Int_val(Field(desc, 1)); + slot =3D Int_val(Field(desc, 2)); + func =3D Int_val(Field(desc, 3)); + + ret =3D xc_domain_test_assign_device(_H(xc_handle), _D(domid), + domain, bus, slot, func); + CAMLreturn(Val_bool(ret =3D=3D 0)); +} + +CAMLprim value stub_xc_domain_assign_device(value xc_handle, value domid= , value desc) +{ + CAMLparam3(xc_handle, domid, desc); + int ret; + int domain, bus, slot, func; + + domain =3D Int_val(Field(desc, 0)); + bus =3D Int_val(Field(desc, 1)); + slot =3D Int_val(Field(desc, 2)); + func =3D Int_val(Field(desc, 3)); + + ret =3D xc_domain_assign_device(_H(xc_handle), _D(domid), + domain, bus, slot, func); + if (ret < 0) + failwith_xc(); + CAMLreturn(Val_unit); +} + +CAMLprim value stub_xc_domain_deassign_device(value xc_handle, value dom= id, value desc) +{ + CAMLparam3(xc_handle, domid, desc); + int ret; + int domain, bus, slot, func; + + domain =3D Int_val(Field(desc, 0)); + bus =3D Int_val(Field(desc, 1)); + slot =3D Int_val(Field(desc, 2)); + func =3D Int_val(Field(desc, 3)); + + ret =3D xc_domain_deassign_device(_H(xc_handle), _D(domid), + domain, bus, slot, func); + if (ret < 0) + failwith_xc(); + CAMLreturn(Val_unit); +} + +CAMLprim value stub_xc_domain_set_timer_mode(value handle, value id, val= ue mode) +{ + CAMLparam3(handle, id, mode); + int ret; + + ret =3D xc_domain_set_timer_mode(_H(handle), _D(id), Int_val(mode)); + if (ret < 0) + failwith_xc(); + CAMLreturn(Val_unit); +} + +CAMLprim value stub_xc_domain_set_hpet(value handle, value id, value mod= e) +{ + CAMLparam3(handle, id, mode); + int ret; + + ret =3D xc_domain_set_hpet(_H(handle), _D(id), Int_val(mode)); + if (ret < 0) + failwith_xc(); + CAMLreturn(Val_unit); +} + +CAMLprim value stub_xc_domain_set_vpt_align(value handle, value id, valu= e mode) +{ + CAMLparam3(handle, id, mode); + int ret; + + ret =3D xc_domain_set_vpt_align(_H(handle), _D(id), Int_val(mode)); + if (ret < 0) + failwith_xc(); + CAMLreturn(Val_unit); +} + +CAMLprim value stub_xc_watchdog(value handle, value domid, value timeout= ) +{ + CAMLparam3(handle, domid, timeout); + int ret; + unsigned int c_timeout =3D Int32_val(timeout); + + ret =3D xc_domain_watchdog(_H(handle), _D(domid), c_timeout); + if (ret < 0) + failwith_xc(); + + CAMLreturn(Val_int(ret)); +} + +CAMLprim value stub_xc_domain_send_s3resume(value handle, value domid) +{ + CAMLparam2(handle, domid); + xc_domain_send_s3resume(_H(handle), _D(domid)); + CAMLreturn(Val_unit); +} + +CAMLprim value stub_xc_domain_get_acpi_s_state(value handle, value domid= ) +{ + CAMLparam2(handle, domid); + int ret; + + ret =3D xc_domain_get_acpi_s_state(_H(handle), _D(domid)); + if (ret < 0) + failwith_xc(); + + CAMLreturn(Val_int(ret)); +} + +/* + * Local variables: + * indent-tabs-mode: t + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ --------------1.7.0 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel --------------1.7.0--