SIM_INTERFACE(x86_msr) { void (*register_handlers)( conf_object_t *cpu, int64 number, x86_msr_getter_func_t getter, lang_void *getter_data, x86_msr_setter_func_t setter, lang_void *setter_data, const char *name); void (*unregister_handlers)( conf_object_t *cpu, int64 number); x86_msr_getter_ret_t (*get)( conf_object_t *cpu, int64 number, x86_msr_access_type_t type); x86_msr_ret_t (*set)( conf_object_t *cpu, int64 number, uint64 value, x86_msr_access_type_t type); const char *(*get_name)( conf_object_t *cpu, int64 number); int64 (*get_number)( conf_object_t *cpu, const char *name); attr_value_t (*get_all_valid_numbers)( conf_object_t *cpu); }; #define X86_MSR_INTERFACE "x86_msr"
The register_handlers function will register get and set functions that will be called every time a read or write access is made to the MSR with number msr.
typedef struct { x86_msr_ret_t status; uint64 value; } x86_msr_getter_ret_t;
typedef enum { Sim_X86_Msr_Ok = Sim_Gen_Spr_Ok, /* Access was OK */ Sim_X86_Msr_GP_Fault, /* Raise #GP fault */ Sim_X86_Msr_Not_Handled /* Pass on to next handler */ } x86_msr_ret_t;
typedef x86_msr_getter_ret_t (*x86_msr_getter_func_t)( conf_object_t *cpu, int64 number, x86_msr_access_type_t type, lang_void *user_data);
typedef x86_msr_ret_t (*x86_msr_setter_func_t)( conf_object_t *cpu, int64 spr_number, uint64 value, x86_msr_access_type_t type, lang_void *user_data);
The type parameter in the get and set functions is one of the following, depending on where from the access originated:
typedef enum { /* Access from a rdmsr/wrmsr instruction */ Sim_X86_Msr_Instruction_Access = Sim_Gen_Spr_Instruction_Access, /* Access through attribute */ Sim_X86_Msr_Attribute_Access = Sim_Gen_Spr_Attribute_Access, /* Access through int_register interface */ Sim_X86_Msr_Int_Register_Access = Sim_Gen_Spr_Int_Register_Access, /* Access during VMX entry/exit */ Sim_X86_Msr_VMX_Access, /* Architectural access without side effects within the CPU model, only reads or writes the register value. However, if it is sent to the platform as a non-inquiry access, that may cause side effects. */ Sim_X86_Msr_Architectural_Access } x86_msr_access_type_t;
The getter function returns the status just like the setter together with the read MSR value. A getter or setter may return the Sim_X86_MSR_Not_Handled return code, in which case the access will pass through to the earlier registered handler (or the default handler if there is no earlier registered handler).
The function unregister_handlers will remove any non-default handlers for a particular MSR.
The get and set functions get and set MSRs, using both model default MSR handlers and handlers installed through this interface.
The function get_name takes number as parameter and returns the name of the MSR.
The function get_number takes the name and returns the MSR number.
The function get_all_valid_numbers returns a list of integers corresponding to all the valid MSRs, including both model default MSRs and MSRs installed through this interface.