Commit c0b34672 authored by Michael Ellerman's avatar Michael Ellerman

Merge branch 'topic/ppc-kvm' into next

Merge the DAWR series, which touches arch code and KVM code and may need
to be merged into the kvm-ppc tree.
parents 34a286a4 96541531
...@@ -464,9 +464,8 @@ static inline void cpu_feature_keys_init(void) { } ...@@ -464,9 +464,8 @@ static inline void cpu_feature_keys_init(void) { }
CPU_FTR_DSCR | CPU_FTR_SAO | \ CPU_FTR_DSCR | CPU_FTR_SAO | \
CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \ CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \
CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \ CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \
CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_DAWR | \ CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_ARCH_207S | \
CPU_FTR_ARCH_207S | CPU_FTR_TM_COMP | CPU_FTR_ARCH_300 | \ CPU_FTR_TM_COMP | CPU_FTR_ARCH_300 | CPU_FTR_PKEY)
CPU_FTR_PKEY)
#define CPU_FTRS_POWER9_DD1 ((CPU_FTRS_POWER9 | CPU_FTR_POWER9_DD1) & \ #define CPU_FTRS_POWER9_DD1 ((CPU_FTRS_POWER9 | CPU_FTR_POWER9_DD1) & \
(~CPU_FTR_SAO)) (~CPU_FTR_SAO))
#define CPU_FTRS_POWER9_DD2_0 CPU_FTRS_POWER9 #define CPU_FTRS_POWER9_DD2_0 CPU_FTRS_POWER9
......
...@@ -47,6 +47,7 @@ static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; } ...@@ -47,6 +47,7 @@ static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; }
void set_breakpoint(struct arch_hw_breakpoint *brk); void set_breakpoint(struct arch_hw_breakpoint *brk);
void __set_breakpoint(struct arch_hw_breakpoint *brk); void __set_breakpoint(struct arch_hw_breakpoint *brk);
bool ppc_breakpoint_available(void);
#ifdef CONFIG_PPC_ADV_DEBUG_REGS #ifdef CONFIG_PPC_ADV_DEBUG_REGS
extern void do_send_trap(struct pt_regs *regs, unsigned long address, extern void do_send_trap(struct pt_regs *regs, unsigned long address,
unsigned long error_code, int brkpt); unsigned long error_code, int brkpt);
......
...@@ -88,6 +88,7 @@ ...@@ -88,6 +88,7 @@
#define H_P8 -61 #define H_P8 -61
#define H_P9 -62 #define H_P9 -62
#define H_TOO_BIG -64 #define H_TOO_BIG -64
#define H_UNSUPPORTED -67
#define H_OVERLAP -68 #define H_OVERLAP -68
#define H_INTERRUPT -69 #define H_INTERRUPT -69
#define H_BAD_DATA -70 #define H_BAD_DATA -70
......
...@@ -713,6 +713,9 @@ static __init void cpufeatures_cpu_quirks(void) ...@@ -713,6 +713,9 @@ static __init void cpufeatures_cpu_quirks(void)
else if ((version & 0xffffefff) == 0x004e0202) else if ((version & 0xffffefff) == 0x004e0202)
cur_cpu_spec->cpu_features |= CPU_FTR_P9_TM_HV_ASSIST | cur_cpu_spec->cpu_features |= CPU_FTR_P9_TM_HV_ASSIST |
CPU_FTR_P9_TM_XER_SO_BUG; CPU_FTR_P9_TM_XER_SO_BUG;
if ((version & 0xffff0000) == 0x004e0000)
cur_cpu_spec->cpu_features &= ~(CPU_FTR_DAWR);
} }
static void __init cpufeatures_setup_finished(void) static void __init cpufeatures_setup_finished(void)
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <asm/hw_breakpoint.h> #include <asm/hw_breakpoint.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/sstep.h> #include <asm/sstep.h>
#include <asm/debug.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
/* /*
...@@ -171,6 +172,8 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp) ...@@ -171,6 +172,8 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
* HW_BREAKPOINT_ALIGN by rounding off to the lower address, the * HW_BREAKPOINT_ALIGN by rounding off to the lower address, the
* 'symbolsize' should satisfy the check below. * 'symbolsize' should satisfy the check below.
*/ */
if (!ppc_breakpoint_available())
return -ENODEV;
length_max = 8; /* DABR */ length_max = 8; /* DABR */
if (cpu_has_feature(CPU_FTR_DAWR)) { if (cpu_has_feature(CPU_FTR_DAWR)) {
length_max = 512 ; /* 64 doublewords */ length_max = 512 ; /* 64 doublewords */
......
...@@ -827,6 +827,18 @@ void set_breakpoint(struct arch_hw_breakpoint *brk) ...@@ -827,6 +827,18 @@ void set_breakpoint(struct arch_hw_breakpoint *brk)
preempt_enable(); preempt_enable();
} }
/* Check if we have DAWR or DABR hardware */
bool ppc_breakpoint_available(void)
{
if (cpu_has_feature(CPU_FTR_DAWR))
return true; /* POWER8 DAWR */
if (cpu_has_feature(CPU_FTR_ARCH_207S))
return false; /* POWER9 with DAWR disabled */
/* DABR: Everything but POWER8 and POWER9 */
return true;
}
EXPORT_SYMBOL_GPL(ppc_breakpoint_available);
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array); DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array);
#endif #endif
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include <asm/switch_to.h> #include <asm/switch_to.h>
#include <asm/tm.h> #include <asm/tm.h>
#include <asm/asm-prototypes.h> #include <asm/asm-prototypes.h>
#include <asm/debug.h>
#define CREATE_TRACE_POINTS #define CREATE_TRACE_POINTS
#include <trace/events/syscalls.h> #include <trace/events/syscalls.h>
...@@ -2378,6 +2379,7 @@ static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, ...@@ -2378,6 +2379,7 @@ static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
struct perf_event_attr attr; struct perf_event_attr attr;
#endif /* CONFIG_HAVE_HW_BREAKPOINT */ #endif /* CONFIG_HAVE_HW_BREAKPOINT */
#ifndef CONFIG_PPC_ADV_DEBUG_REGS #ifndef CONFIG_PPC_ADV_DEBUG_REGS
bool set_bp = true;
struct arch_hw_breakpoint hw_brk; struct arch_hw_breakpoint hw_brk;
#endif #endif
...@@ -2411,9 +2413,10 @@ static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, ...@@ -2411,9 +2413,10 @@ static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
hw_brk.address = data & (~HW_BRK_TYPE_DABR); hw_brk.address = data & (~HW_BRK_TYPE_DABR);
hw_brk.type = (data & HW_BRK_TYPE_DABR) | HW_BRK_TYPE_PRIV_ALL; hw_brk.type = (data & HW_BRK_TYPE_DABR) | HW_BRK_TYPE_PRIV_ALL;
hw_brk.len = 8; hw_brk.len = 8;
set_bp = (data) && (hw_brk.type & HW_BRK_TYPE_RDWR);
#ifdef CONFIG_HAVE_HW_BREAKPOINT #ifdef CONFIG_HAVE_HW_BREAKPOINT
bp = thread->ptrace_bps[0]; bp = thread->ptrace_bps[0];
if ((!data) || !(hw_brk.type & HW_BRK_TYPE_RDWR)) { if (!set_bp) {
if (bp) { if (bp) {
unregister_hw_breakpoint(bp); unregister_hw_breakpoint(bp);
thread->ptrace_bps[0] = NULL; thread->ptrace_bps[0] = NULL;
...@@ -2450,6 +2453,9 @@ static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, ...@@ -2450,6 +2453,9 @@ static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
return PTR_ERR(bp); return PTR_ERR(bp);
} }
#else /* !CONFIG_HAVE_HW_BREAKPOINT */
if (set_bp && (!ppc_breakpoint_available()))
return -ENODEV;
#endif /* CONFIG_HAVE_HW_BREAKPOINT */ #endif /* CONFIG_HAVE_HW_BREAKPOINT */
task->thread.hw_brk = hw_brk; task->thread.hw_brk = hw_brk;
#else /* CONFIG_PPC_ADV_DEBUG_REGS */ #else /* CONFIG_PPC_ADV_DEBUG_REGS */
...@@ -2904,6 +2910,9 @@ static long ppc_set_hwdebug(struct task_struct *child, ...@@ -2904,6 +2910,9 @@ static long ppc_set_hwdebug(struct task_struct *child,
if (child->thread.hw_brk.address) if (child->thread.hw_brk.address)
return -ENOSPC; return -ENOSPC;
if (!ppc_breakpoint_available())
return -ENODEV;
child->thread.hw_brk = brk; child->thread.hw_brk = brk;
return 1; return 1;
...@@ -3052,7 +3061,10 @@ long arch_ptrace(struct task_struct *child, long request, ...@@ -3052,7 +3061,10 @@ long arch_ptrace(struct task_struct *child, long request,
#endif #endif
#else /* !CONFIG_PPC_ADV_DEBUG_REGS */ #else /* !CONFIG_PPC_ADV_DEBUG_REGS */
dbginfo.num_instruction_bps = 0; dbginfo.num_instruction_bps = 0;
dbginfo.num_data_bps = 1; if (ppc_breakpoint_available())
dbginfo.num_data_bps = 1;
else
dbginfo.num_data_bps = 0;
dbginfo.num_condition_regs = 0; dbginfo.num_condition_regs = 0;
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
dbginfo.data_bp_alignment = 8; dbginfo.data_bp_alignment = 8;
......
...@@ -741,6 +741,8 @@ static int kvmppc_h_set_mode(struct kvm_vcpu *vcpu, unsigned long mflags, ...@@ -741,6 +741,8 @@ static int kvmppc_h_set_mode(struct kvm_vcpu *vcpu, unsigned long mflags,
case H_SET_MODE_RESOURCE_SET_DAWR: case H_SET_MODE_RESOURCE_SET_DAWR:
if (!kvmppc_power8_compatible(vcpu)) if (!kvmppc_power8_compatible(vcpu))
return H_P2; return H_P2;
if (!ppc_breakpoint_available())
return H_P2;
if (mflags) if (mflags)
return H_UNSUPPORTED_FLAG_START; return H_UNSUPPORTED_FLAG_START;
if (value2 & DABRX_HYP) if (value2 & DABRX_HYP)
......
...@@ -892,8 +892,14 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S) ...@@ -892,8 +892,14 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
ld r6, VCPU_DAWRX(r4) ld r6, VCPU_DAWRX(r4)
ld r7, VCPU_CIABR(r4) ld r7, VCPU_CIABR(r4)
ld r8, VCPU_TAR(r4) ld r8, VCPU_TAR(r4)
/*
* Handle broken DAWR case by not writing it. This means we
* can still store the DAWR register for migration.
*/
BEGIN_FTR_SECTION
mtspr SPRN_DAWR, r5 mtspr SPRN_DAWR, r5
mtspr SPRN_DAWRX, r6 mtspr SPRN_DAWRX, r6
END_FTR_SECTION_IFSET(CPU_FTR_DAWR)
mtspr SPRN_CIABR, r7 mtspr SPRN_CIABR, r7
mtspr SPRN_TAR, r8 mtspr SPRN_TAR, r8
ld r5, VCPU_IC(r4) ld r5, VCPU_IC(r4)
...@@ -1855,6 +1861,10 @@ BEGIN_FTR_SECTION ...@@ -1855,6 +1861,10 @@ BEGIN_FTR_SECTION
ld r6, STACK_SLOT_DAWR(r1) ld r6, STACK_SLOT_DAWR(r1)
ld r7, STACK_SLOT_DAWRX(r1) ld r7, STACK_SLOT_DAWRX(r1)
mtspr SPRN_CIABR, r5 mtspr SPRN_CIABR, r5
/*
* If the DAWR doesn't work, it's ok to write these here as
* this value should always be zero
*/
mtspr SPRN_DAWR, r6 mtspr SPRN_DAWR, r6
mtspr SPRN_DAWRX, r7 mtspr SPRN_DAWRX, r7
END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
...@@ -2563,8 +2573,14 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) ...@@ -2563,8 +2573,14 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
li r3,0 li r3,0
blr blr
2:
BEGIN_FTR_SECTION
/* POWER9 with disabled DAWR */
li r3, H_UNSUPPORTED
blr
END_FTR_SECTION_IFCLR(CPU_FTR_DAWR)
/* Emulate H_SET_DABR/X on P8 for the sake of compat mode guests */ /* Emulate H_SET_DABR/X on P8 for the sake of compat mode guests */
2: rlwimi r5, r4, 5, DAWRX_DR | DAWRX_DW rlwimi r5, r4, 5, DAWRX_DR | DAWRX_DW
rlwimi r5, r4, 2, DAWRX_WT rlwimi r5, r4, 2, DAWRX_WT
clrrdi r4, r4, 3 clrrdi r4, r4, 3
std r4, VCPU_DAWR(r3) std r4, VCPU_DAWR(r3)
......
...@@ -1302,6 +1302,10 @@ bpt_cmds(void) ...@@ -1302,6 +1302,10 @@ bpt_cmds(void)
static const char badaddr[] = "Only kernel addresses are permitted for breakpoints\n"; static const char badaddr[] = "Only kernel addresses are permitted for breakpoints\n";
int mode; int mode;
case 'd': /* bd - hardware data breakpoint */ case 'd': /* bd - hardware data breakpoint */
if (!ppc_breakpoint_available()) {
printf("Hardware data breakpoint not supported on this cpu\n");
break;
}
mode = 7; mode = 7;
cmd = inchar(); cmd = inchar();
if (cmd == 'r') if (cmd == 'r')
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment