Skip to content

Commit

Permalink
target-ppc: Handle additional bits in H_GET_CPU_CHARACTERISTICS
Browse files Browse the repository at this point in the history
The hcall H_GET_CPU_CHARACTERISTICS is used by the guest to determine
information about the required behaviours and available characteristics
of the cpu.

Bits may be added to this hcall, the information for which is queried
from the hypervisor using the KVM_PPC_GET_CPU_CHAR ioctl. In order to
handle the case where additional bits may be added to this hcall, and
thus to the ioctl, relax the parsing in qemu so that there is minimal
modification of the data before it is passed to the guest.

Signed-off-by: Suraj Jitindar Singh <[email protected]>
Signed-off-by: Ricardo M. Matinata <[email protected]>
  • Loading branch information
sjitindarsingh authored and Ricardo M. Matinata committed Mar 6, 2018
1 parent 8188e66 commit 9e7dc71
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 96 deletions.
64 changes: 14 additions & 50 deletions hw/ppc/spapr_hcall.c
Original file line number Diff line number Diff line change
Expand Up @@ -1044,57 +1044,21 @@ static target_ulong h_get_cpu_characteristics(PowerPCCPU *cpu,
target_ulong opcode,
target_ulong *args)
{
uint64_t characteristics = H_CPU_CHAR_HON_BRANCH_HINTS &
~H_CPU_CHAR_THR_RECONF_TRIG;
uint64_t behaviour = H_CPU_BEHAV_FAVOUR_SECURITY;
int safe_cache = kvmppc_get_cap_safe_cache();
int safe_bounds_check = kvmppc_get_cap_safe_bounds_check();
int safe_indirect_branch = kvmppc_get_cap_safe_indirect_branch();

switch (safe_cache) {
case 1:
characteristics |= H_CPU_CHAR_L1D_FLUSH_ORI30;
characteristics |= H_CPU_CHAR_L1D_FLUSH_TRIG2;
characteristics |= H_CPU_CHAR_L1D_THREAD_PRIV;
behaviour |= H_CPU_BEHAV_L1D_FLUSH_PR;
break;
case 2:
break;
default: /* broken */
if (safe_cache != 0) {
error_report("Invalid value for safe cache (%d), assuming broken",
safe_cache);
uint64_t characteristics = kvmppc_get_cap_ppc_cpu_char_character();
uint64_t behaviour = kvmppc_get_cap_ppc_cpu_char_behaviour();

characteristics |= H_CPU_CHAR_HON_BRANCH_HINTS;

if (behaviour & H_CPU_BEHAV_L1D_FLUSH_PR) {
/*
* To enable P8->P9 & P9->P8 migration, if either of the cache flush
* instructions are available, then tell the guest to use both.
*/
if (characteristics & (H_CPU_CHAR_L1D_FLUSH_ORI30 |
H_CPU_CHAR_L1D_FLUSH_TRIG2)) {
characteristics |= H_CPU_CHAR_L1D_FLUSH_ORI30 |
H_CPU_CHAR_L1D_FLUSH_TRIG2;
}
behaviour |= H_CPU_BEHAV_L1D_FLUSH_PR;
break;
}

switch (safe_bounds_check) {
case 1:
characteristics |= H_CPU_CHAR_SPEC_BAR_ORI31;
behaviour |= H_CPU_BEHAV_BNDS_CHK_SPEC_BAR;
break;
case 2:
break;
default: /* broken */
if (safe_bounds_check != 0) {
error_report("Invalid value for safe bounds check (%d), assuming broken",
safe_bounds_check);
}
behaviour |= H_CPU_BEHAV_BNDS_CHK_SPEC_BAR;
break;
}

switch (safe_indirect_branch) {
case 2:
characteristics |= H_CPU_CHAR_BCCTRL_SERIALISED;
break;
default: /* broken */
if (safe_indirect_branch != 0) {
error_report("Invalid value for safe indirect branch (%d), assuming broken",
safe_indirect_branch);
}
break;
}

args[0] = characteristics;
Expand Down
42 changes: 8 additions & 34 deletions target-ppc/kvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,8 @@ static int cap_ppc_watchdog;
static int cap_papr;
static int cap_htab_fd;
static int cap_fixup_hcalls;
static int cap_ppc_safe_cache;
static int cap_ppc_safe_bounds_check;
static int cap_ppc_safe_indirect_branch;
static uint64_t cap_ppc_cpu_char_character;
static uint64_t cap_ppc_cpu_char_behaviour;

static uint32_t debug_inst_opcode;

Expand Down Expand Up @@ -2350,11 +2349,6 @@ static void kvmppc_get_cpu_characteristics(KVMState *s)
struct kvm_ppc_cpu_char c;
int ret;

/* Assume broken */
cap_ppc_safe_cache = 0;
cap_ppc_safe_bounds_check = 0;
cap_ppc_safe_indirect_branch = 0;

ret = kvm_vm_check_extension(s, KVM_CAP_PPC_GET_CPU_CHAR);
if (!ret) {
return;
Expand All @@ -2363,39 +2357,19 @@ static void kvmppc_get_cpu_characteristics(KVMState *s)
if (ret < 0) {
return;
}
/* Parse and set cap_ppc_safe_cache */
if (~c.behaviour & c.b_mask & H_CPU_BEHAV_L1D_FLUSH_PR) {
cap_ppc_safe_cache = 2;
} else if ((c.character & c.c_mask & H_CPU_CHAR_L1D_THREAD_PRIV) &&
(c.character & c.c_mask & (H_CPU_CHAR_L1D_FLUSH_ORI30 |
H_CPU_CHAR_L1D_FLUSH_TRIG2))) {
cap_ppc_safe_cache = 1;
}
/* Parse and set cap_ppc_safe_bounds_check */
if (~c.behaviour & c.b_mask & H_CPU_BEHAV_BNDS_CHK_SPEC_BAR) {
cap_ppc_safe_bounds_check = 2;
} else if (c.character & c.c_mask & H_CPU_CHAR_SPEC_BAR_ORI31) {
cap_ppc_safe_bounds_check = 1;
}
/* Parse and set cap_ppc_safe_indirect_branch */
if (c.character & H_CPU_CHAR_BCCTRL_SERIALISED) {
cap_ppc_safe_indirect_branch = 2;
}
}

int kvmppc_get_cap_safe_cache(void)
{
return cap_ppc_safe_cache;
cap_ppc_cpu_char_character = c.character & c.c_mask;
cap_ppc_cpu_char_behaviour = c.behaviour & c.b_mask;
}

int kvmppc_get_cap_safe_bounds_check(void)
uint64_t kvmppc_get_cap_ppc_cpu_char_character(void)
{
return cap_ppc_safe_bounds_check;
return cap_ppc_cpu_char_character;
}

int kvmppc_get_cap_safe_indirect_branch(void)
uint64_t kvmppc_get_cap_ppc_cpu_char_behaviour(void)
{
return cap_ppc_safe_indirect_branch;
return cap_ppc_cpu_char_behaviour;
}

static PowerPCCPUClass *ppc_cpu_get_family_class(PowerPCCPUClass *pcc)
Expand Down
18 changes: 6 additions & 12 deletions target-ppc/kvm_ppc.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,8 @@ void kvmppc_hash64_free_pteg(uint64_t token);
void kvmppc_hash64_write_pte(CPUPPCState *env, target_ulong pte_index,
target_ulong pte0, target_ulong pte1);
bool kvmppc_has_cap_fixup_hcalls(void);
int kvmppc_get_cap_safe_cache(void);
int kvmppc_get_cap_safe_bounds_check(void);
int kvmppc_get_cap_safe_indirect_branch(void);
uint64_t kvmppc_get_cap_ppc_cpu_char_character(void);
uint64_t kvmppc_get_cap_ppc_cpu_char_behaviour(void);
int kvmppc_enable_hwrng(void);
int kvmppc_put_books_sregs(PowerPCCPU *cpu);
PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void);
Expand Down Expand Up @@ -247,19 +246,14 @@ static inline bool kvmppc_has_cap_fixup_hcalls(void)
abort();
}

static inline int kvmppc_get_cap_safe_cache(void)
static inline uint64_t kvmppc_get_cap_ppc_cpu_char_character(void)
{
return 0;
}

static inline int kvmppc_get_cap_safe_bounds_check(void)
{
return 0;
return 0ULL;
}

static inline int kvmppc_get_cap_safe_indirect_branch(void)
static inline uint64_t kvmppc_get_cap_ppc_cpu_char_behaviour(void)
{
return 0;
return 0ULL;
}

static inline int kvmppc_enable_hwrng(void)
Expand Down

0 comments on commit 9e7dc71

Please sign in to comment.