* [PATCH 3/5] powerpc/perf: Avoid mutating event in power8_get_constraint()
From: Michael Ellerman @ 2014-03-06 6:59 UTC (permalink / raw)
To: linuxppc-dev; +Cc: ymanton, Paul Mackerras, khandual
In-Reply-To: <1394089152-603-1-git-send-email-mpe@ellerman.id.au>
We only need to mask the EBB bit out of the event for the check of the
special PMC 5 & 6 events. So use a local to do it just for that code,
rather than changing the event value for the life of the function.
While we're there move the set of mask and value after all the checks.
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
arch/powerpc/perf/power8-pmu.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c
index 26905ce..04c1c77 100644
--- a/arch/powerpc/perf/power8-pmu.c
+++ b/arch/powerpc/perf/power8-pmu.c
@@ -268,18 +268,20 @@ static int power8_get_constraint(u64 event, unsigned long *maskp, unsigned long
cache = (event >> EVENT_CACHE_SEL_SHIFT) & EVENT_CACHE_SEL_MASK;
ebb = (event >> EVENT_EBB_SHIFT) & EVENT_EBB_MASK;
- /* Clear the EBB bit in the event, so event checks work below */
- event &= ~(EVENT_EBB_MASK << EVENT_EBB_SHIFT);
-
if (pmc) {
+ u64 base_event;
+
if (pmc > 6)
return -1;
- mask |= CNST_PMC_MASK(pmc);
- value |= CNST_PMC_VAL(pmc);
+ /* Ignore Linux defined bits when checking event below */
+ base_event = event & ~(EVENT_EBB_MASK << EVENT_EBB_SHIFT);
- if (pmc >= 5 && event != 0x500fa && event != 0x600f4)
+ if (pmc >= 5 && base_event != 0x500fa && base_event != 0x600f4)
return -1;
+
+ mask |= CNST_PMC_MASK(pmc);
+ value |= CNST_PMC_VAL(pmc);
}
if (pmc <= 4) {
--
1.8.3.2
^ permalink raw reply related
* [PATCH 4/5] powerpc/perf: Add BHRB constraint and IFM MMCRA handling for EBB
From: Michael Ellerman @ 2014-03-06 6:59 UTC (permalink / raw)
To: linuxppc-dev; +Cc: ymanton, Paul Mackerras, khandual
In-Reply-To: <1394089152-603-1-git-send-email-mpe@ellerman.id.au>
We want a way for users of EBB (Event Based Branches) to also access the
BHRB (Branch History Rolling Buffer). EBB does not interoperate with our
existing BHRB support, which is wired into the generic Linux branch
stack sampling support.
To support EBB & BHRB we add three new bits to the event code. The first
bit indicates that the event wants access to the BHRB, and the other two
bits indicate the desired IFM (Instruction Filtering Mode).
We allow multiple events to request access to the BHRB, but they must
agree on the IFM value. Events which are not interested in the BHRB can
also interoperate with events which do.
Finally we program the desired IFM value into MMCRA. Although we do this
for every event, we know that the value will be identical for all events
that request BHRB access.
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
arch/powerpc/perf/power8-pmu.c | 53 +++++++++++++++++++++++++++++++++++-------
1 file changed, 44 insertions(+), 9 deletions(-)
diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c
index 04c1c77..babc3c0 100644
--- a/arch/powerpc/perf/power8-pmu.c
+++ b/arch/powerpc/perf/power8-pmu.c
@@ -62,9 +62,11 @@
*
* 60 56 52 48 44 40 36 32
* | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - |
- * | [ thresh_cmp ] [ thresh_ctl ]
- * | |
- * *- EBB (Linux) thresh start/stop OR FAB match -*
+ * | | [ ] [ thresh_cmp ] [ thresh_ctl ]
+ * | | | |
+ * | | *- IFM (Linux) thresh start/stop OR FAB match -*
+ * | *- BHRB (Linux)
+ * *- EBB (Linux)
*
* 28 24 20 16 12 8 4 0
* | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - |
@@ -114,10 +116,18 @@
* MMCRA[57:59] = sample[0:2] (RAND_SAMP_ELIG)
* MMCRA[61:62] = sample[3:4] (RAND_SAMP_MODE)
*
+ * if EBB and BHRB:
+ * MMCRA[32:33] = IFM
+ *
*/
#define EVENT_EBB_MASK 1ull
#define EVENT_EBB_SHIFT PERF_EVENT_CONFIG_EBB_SHIFT
+#define EVENT_BHRB_MASK 1ull
+#define EVENT_BHRB_SHIFT 62
+#define EVENT_WANTS_BHRB (EVENT_BHRB_MASK << EVENT_BHRB_SHIFT)
+#define EVENT_IFM_MASK 3ull
+#define EVENT_IFM_SHIFT 60
#define EVENT_THR_CMP_SHIFT 40 /* Threshold CMP value */
#define EVENT_THR_CMP_MASK 0x3ff
#define EVENT_THR_CTL_SHIFT 32 /* Threshold control value (start/stop) */
@@ -142,6 +152,12 @@
#define EVENT_IS_MARKED (EVENT_MARKED_MASK << EVENT_MARKED_SHIFT)
#define EVENT_PSEL_MASK 0xff /* PMCxSEL value */
+/* Bits defined by Linux */
+#define EVENT_LINUX_MASK \
+ ((EVENT_EBB_MASK << EVENT_EBB_SHIFT) | \
+ (EVENT_BHRB_MASK << EVENT_BHRB_SHIFT) | \
+ (EVENT_IFM_MASK << EVENT_IFM_SHIFT))
+
#define EVENT_VALID_MASK \
((EVENT_THRESH_MASK << EVENT_THRESH_SHIFT) | \
(EVENT_SAMPLE_MASK << EVENT_SAMPLE_SHIFT) | \
@@ -150,7 +166,7 @@
(EVENT_UNIT_MASK << EVENT_UNIT_SHIFT) | \
(EVENT_COMBINE_MASK << EVENT_COMBINE_SHIFT) | \
(EVENT_MARKED_MASK << EVENT_MARKED_SHIFT) | \
- (EVENT_EBB_MASK << EVENT_EBB_SHIFT) | \
+ EVENT_LINUX_MASK | \
EVENT_PSEL_MASK)
/* MMCRA IFM bits - POWER8 */
@@ -174,10 +190,11 @@
*
* 28 24 20 16 12 8 4 0
* | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - |
- * | [ ] [ sample ] [ ] [6] [5] [4] [3] [2] [1]
- * EBB -* | |
- * | | Count of events for each PMC.
- * L1 I/D qualifier -* | p1, p2, p3, p4, p5, p6.
+ * [ ] | [ ] [ sample ] [ ] [6] [5] [4] [3] [2] [1]
+ * | | | |
+ * BHRB IFM -* | | | Count of events for each PMC.
+ * EBB -* | | p1, p2, p3, p4, p5, p6.
+ * L1 I/D qualifier -* |
* nc - number of counters -*
*
* The PMC fields P1..P6, and NC, are adder fields. As we accumulate constraints
@@ -196,6 +213,9 @@
#define CNST_EBB_VAL(v) (((v) & EVENT_EBB_MASK) << 24)
#define CNST_EBB_MASK CNST_EBB_VAL(EVENT_EBB_MASK)
+#define CNST_IFM_VAL(v) (((v) & EVENT_IFM_MASK) << 25)
+#define CNST_IFM_MASK CNST_IFM_VAL(EVENT_IFM_MASK)
+
#define CNST_L1_QUAL_VAL(v) (((v) & 3) << 22)
#define CNST_L1_QUAL_MASK CNST_L1_QUAL_VAL(3)
@@ -242,6 +262,7 @@
#define MMCRA_THR_SEL_SHIFT 16
#define MMCRA_THR_CMP_SHIFT 32
#define MMCRA_SDAR_MODE_TLB (1ull << 42)
+#define MMCRA_IFM_SHIFT 30
static inline bool event_is_fab_match(u64 event)
@@ -275,7 +296,7 @@ static int power8_get_constraint(u64 event, unsigned long *maskp, unsigned long
return -1;
/* Ignore Linux defined bits when checking event below */
- base_event = event & ~(EVENT_EBB_MASK << EVENT_EBB_SHIFT);
+ base_event = event & ~EVENT_LINUX_MASK;
if (pmc >= 5 && base_event != 0x500fa && base_event != 0x600f4)
return -1;
@@ -345,6 +366,15 @@ static int power8_get_constraint(u64 event, unsigned long *maskp, unsigned long
/* EBB events must specify the PMC */
return -1;
+ if (event & EVENT_WANTS_BHRB) {
+ if (!ebb)
+ /* Only EBB events can request BHRB */
+ return -1;
+
+ mask |= CNST_IFM_MASK;
+ value |= CNST_IFM_VAL(event >> EVENT_IFM_SHIFT);
+ }
+
/*
* All events must agree on EBB, either all request it or none.
* EBB events are pinned & exclusive, so this should never actually
@@ -434,6 +464,11 @@ static int power8_compute_mmcr(u64 event[], int n_ev,
mmcra |= val << MMCRA_THR_CMP_SHIFT;
}
+ if (event[i] & EVENT_WANTS_BHRB) {
+ val = (event[i] >> EVENT_IFM_SHIFT) & EVENT_IFM_MASK;
+ mmcra |= val << MMCRA_IFM_SHIFT;
+ }
+
hwc[i] = pmc - 1;
}
--
1.8.3.2
^ permalink raw reply related
* [PATCH 5/5] powerpc/perf: Enable BHRB access for EBB events
From: Michael Ellerman @ 2014-03-06 6:59 UTC (permalink / raw)
To: linuxppc-dev; +Cc: ymanton, Paul Mackerras, khandual
In-Reply-To: <1394089152-603-1-git-send-email-mpe@ellerman.id.au>
The previous commit added constraint and register handling to allow
processes using EBB (Event Based Branches) to request access to the BHRB
(Branch History Rolling Buffer).
With that in place we can allow processes using EBB to access the BHRB.
This is achieved by setting BHRBA in MMCR0 when we enable EBB access. We
must also clear BHRBA when we are disabling.
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
arch/powerpc/include/asm/reg.h | 1 +
arch/powerpc/perf/core-book3s.c | 10 ++++++----
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 90c06ec..d48ce94 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -664,6 +664,7 @@
#define MMCR0_PMXE 0x04000000UL /* performance monitor exception enable */
#define MMCR0_FCECE 0x02000000UL /* freeze ctrs on enabled cond or event */
#define MMCR0_TBEE 0x00400000UL /* time base exception enable */
+#define MMCR0_BHRBA 0x00200000UL /* BHRB Access allowed in userspace */
#define MMCR0_EBE 0x00100000UL /* Event based branch enable */
#define MMCR0_PMCC 0x000c0000UL /* PMC control */
#define MMCR0_PMCC_U6 0x00080000UL /* PMC1-6 are R/W by user (PR) */
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 4b2ba0c..a75bb69 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -78,6 +78,7 @@ static unsigned int freeze_events_kernel = MMCR0_FCS;
#define MMCR0_FC56 0
#define MMCR0_PMAO 0
#define MMCR0_EBE 0
+#define MMCR0_BHRBA 0
#define MMCR0_PMCC 0
#define MMCR0_PMCC_U6 0
@@ -545,8 +546,8 @@ static unsigned long ebb_switch_in(bool ebb, unsigned long mmcr0)
if (!ebb)
goto out;
- /* Enable EBB and read/write to all 6 PMCs for userspace */
- mmcr0 |= MMCR0_EBE | MMCR0_PMCC_U6;
+ /* Enable EBB and read/write to all 6 PMCs and BHRB for userspace */
+ mmcr0 |= MMCR0_EBE | MMCR0_BHRBA | MMCR0_PMCC_U6;
/* Add any bits from the user reg, FC or PMAO */
mmcr0 |= current->thread.mmcr0;
@@ -976,11 +977,12 @@ static void power_pmu_disable(struct pmu *pmu)
}
/*
- * Set the 'freeze counters' bit, clear EBE/PMCC/PMAO/FC56.
+ * Set the 'freeze counters' bit, clear EBE/BHRBA/PMCC/PMAO/FC56
*/
val = mmcr0 = mfspr(SPRN_MMCR0);
val |= MMCR0_FC;
- val &= ~(MMCR0_EBE | MMCR0_PMCC | MMCR0_PMAO | MMCR0_FC56);
+ val &= ~(MMCR0_EBE | MMCR0_BHRBA | MMCR0_PMCC | MMCR0_PMAO |
+ MMCR0_FC56);
/*
* The barrier is to make sure the mtspr has been
--
1.8.3.2
^ permalink raw reply related
* RE: [PATCH 3/3] perf: Use 64-bit value when comparing sample_regs
From: David Laight @ 2014-03-06 9:44 UTC (permalink / raw)
To: 'Sukadev Bhattiprolu', Arnaldo Carvalho de Melo
Cc: Michael Ellerman, linux-kernel@vger.kernel.org, Stephane Eranian,
linuxppc-dev@ozlabs.org, Paul Mackerras, Jiri Olsa
In-Reply-To: <1394080919-17957-4-git-send-email-sukadev@linux.vnet.ibm.com>
RnJvbTogU3VrYWRldiBCaGF0dGlwcm9sdQ0KPiBXaGVuIGNoZWNraW5nIHdoZXRoZXIgYSBiaXQg
cmVwcmVzZW50aW5nIGEgcmVnaXN0ZXIgaXMgc2V0IGluDQo+IHNhbXBsZV9yZWdzLCBhIDY0LWJp
dCBtYXNrLCB1c2UgNjQtYml0IHZhbHVlICgxTEwpLg0KPiANCj4gU2lnbmVkLW9mZi1ieTogU3Vr
YWRldiBCaGF0dGlwcm9sdSA8c3VrYWRldkBsaW51eC52bmV0LmlibS5jb20+DQo+IC0tLQ0KPiAg
dG9vbHMvcGVyZi91dGlsL3Vud2luZC5jIHwgICAgNCArKy0tDQo+ICAxIGZpbGUgY2hhbmdlZCwg
MiBpbnNlcnRpb25zKCspLCAyIGRlbGV0aW9ucygtKQ0KPiANCj4gZGlmZiAtLWdpdCBhL3Rvb2xz
L3BlcmYvdXRpbC91bndpbmQuYyBiL3Rvb2xzL3BlcmYvdXRpbC91bndpbmQuYw0KPiBpbmRleCA3
NDJmMjNiLi4yYjg4OGM2IDEwMDY0NA0KPiAtLS0gYS90b29scy9wZXJmL3V0aWwvdW53aW5kLmMN
Cj4gKysrIGIvdG9vbHMvcGVyZi91dGlsL3Vud2luZC5jDQo+IEBAIC0zOTYsMTEgKzM5NiwxMSBA
QCBzdGF0aWMgaW50IHJlZ192YWx1ZSh1bndfd29yZF90ICp2YWxwLCBzdHJ1Y3QgcmVnc19kdW1w
ICpyZWdzLCBpbnQgaWQsDQo+ICB7DQo+ICAJaW50IGksIGlkeCA9IDA7DQo+IA0KPiAtCWlmICgh
KHNhbXBsZV9yZWdzICYgKDEgPDwgaWQpKSkNCj4gKwlpZiAoIShzYW1wbGVfcmVncyAmICgxTEwg
PDwgaWQpKSkNCj4gIAkJcmV0dXJuIC1FSU5WQUw7DQo+IA0KPiAgCWZvciAoaSA9IDA7IGkgPCBp
ZDsgaSsrKSB7DQo+IC0JCWlmIChzYW1wbGVfcmVncyAmICgxIDw8IGkpKQ0KPiArCQlpZiAoc2Ft
cGxlX3JlZ3MgJiAoMUxMIDw8IGkpKQ0KPiAgCQkJaWR4Kys7DQo+ICAJfQ0KDQpUaGVyZSBhcmUg
bXVjaCBmYXN0ZXIgd2F5cyB0byBjb3VudCB0aGUgbnVtYmVyIG9mIHNldCBiaXRzLCBlc3BlY2lh
bGx5DQppZiB5b3UgbWlnaHQgbmVlZCB0byBjaGVjayBhIHNpZ25pZmljYW50IG51bWJlciBvZiBi
aXRzLg0KVGhlcmUgbWlnaHQgZXZlbiBiZSBhIGZ1bmN0aW9uIGRlZmluZWQgc29tZXdoZXJlIHRv
IGRvIGl0Lg0KQmFzaWNhbGx5IHlvdSBqdXN0IGFkZCB1cCB0aGUgYml0cywgZm9yIDE2IGJpdCBp
dCB3b3VsZCBiZToNCgl2YWwgPSAodmFsICYgMHg1NTU1KSArICh2YWwgPj4gMSkgJiAweDU1NTU7
DQoJdmFsID0gKHZhbCAmIDB4MzMzMykgKyAodmFsID4+IDIpICYgMHgzMzMzOw0KCXZhbCA9ICh2
YWwgJiAweDBmMGYpICsgKHZhbCA+PiA0KSAmIDB4MGYwZjsNCgl2YWwgPSAodmFsICYgMHgwMGZm
KSArICh2YWwgPj4gOCkgJiAweDAwZmY7DQpBcyB0aGUgc2l6ZSBvZiB0aGUgd29yayBpbmNyZWFz
ZXMgdGhlIGltcHJvdmVtZW50IGlzIG1vcmUgc2lnbmlmaWNhbnQuDQooU29tZSBvZiB0aGUgbGF0
ZXIgbWFza2luZyBjYW4gcHJvYmFibHkgYmUgcHJvdmVuIHVubmVjZXNzYXJ5LikNCg0KCURhdmlk
DQoNCg==
^ permalink raw reply
* [PATCH 1/2] Revert "KVM: PPC: Book3S HV: Add new state for transactional memory"
From: Aneesh Kumar K.V @ 2014-03-06 10:36 UTC (permalink / raw)
To: agraf, benh, paulus; +Cc: linuxppc-dev, kvm, kvm-ppc, Aneesh Kumar K.V
From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
This reverts commit 7b490411c37f7ab7965cbdfe5e3ec28eadb6db5b which cause
the below crash in the host.
Unable to handle kernel paging request for data at address 0xf00000001223f278
Faulting instruction address: 0xc000000000202a00
cpu 0x30: Vector: 300 (Data Access) at [c000001e4debb2d0]
pc: c000000000202a00: .kfree+0x40/0x200
lr: c000000000098338: .kvmppc_core_destroy_vm_hv+0x38/0x90
sp: c000001e4debb550
msr: 9000000000009032
dar: f00000001223f278
dsisr: 40000000
current = 0xc000001e4de195c0
paca = 0xc00000000fefb000 softe: 0 irq_happened: 0x01
pid = 29379, comm = qemu-system-ppc
enter ? for help
[c000001e4debb5e0] c000000000098338 .kvmppc_core_destroy_vm_hv+0x38/0x90
[c000001e4debb670] c000000000087f80 .kvmppc_core_destroy_vm+0x30/0x70
[c000001e4debb6f0] c000000000084f28 .kvm_arch_destroy_vm+0xd8/0x120
[c000001e4debb780] c000000000080218 .kvm_put_kvm+0x198/0x2e0
[c000001e4debb820] c0000000000880d4 .kvm_spapr_tce_release+0xe4/0x110
[c000001e4debb8b0] c000000000218578 .__fput+0xb8/0x2a0
[c000001e4debb950] c0000000000d9af4 .task_work_run+0x114/0x150
[c000001e4debb9f0] c0000000000b31e8 .do_exit+0x328/0xbc0
[c000001e4debbae0] c0000000000b4cd4 .do_group_exit+0x54/0xf0
[c000001e4debbb70] c0000000000c8448 .get_signal_to_deliver+0x1e8/0x6f0
[c000001e4debbc70] c000000000017ee4 .do_signal+0x54/0x320
[c000001e4debbdb0] c0000000000182e8 .do_notify_resume+0x68/0x80
[c000001e4debbe30] c00000000000a7b0 .ret_from_except_lite+0x5c/0x60
--- Exception: c00 (System Call) at 00003fffb38a4744
SP (3ffd36ffe360) is in userspace
30:mon> zr
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/kvm_host.h | 24 ++---------
arch/powerpc/kernel/asm-offsets.c | 19 ++-------
arch/powerpc/kvm/book3s_hv.c | 4 --
arch/powerpc/kvm/book3s_hv_rmhandlers.S | 75 +--------------------------------
4 files changed, 8 insertions(+), 114 deletions(-)
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 1eaea2dea174..7726a3bc8ff0 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -475,6 +475,9 @@ struct kvm_vcpu_arch {
ulong ppr;
ulong pspb;
ulong fscr;
+ ulong tfhar;
+ ulong tfiar;
+ ulong texasr;
ulong ebbhr;
ulong ebbrr;
ulong bescr;
@@ -523,27 +526,6 @@ struct kvm_vcpu_arch {
u64 siar;
u64 sdar;
u64 sier;
-#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
- u64 tfhar;
- u64 texasr;
- u64 tfiar;
-
- u32 cr_tm;
- u64 lr_tm;
- u64 ctr_tm;
- u64 amr_tm;
- u64 ppr_tm;
- u64 dscr_tm;
- u64 tar_tm;
-
- ulong gpr_tm[32];
-
- struct thread_fp_state fp_tm;
-
- struct thread_vr_state vr_tm;
- u32 vrsave_tm; /* also USPRG0 */
-
-#endif
#ifdef CONFIG_KVM_EXIT_TIMING
struct mutex exit_timing_lock;
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index b5aacf72ae6f..936d445b961a 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -534,6 +534,9 @@ int main(void)
DEFINE(VCPU_PPR, offsetof(struct kvm_vcpu, arch.ppr));
DEFINE(VCPU_FSCR, offsetof(struct kvm_vcpu, arch.fscr));
DEFINE(VCPU_PSPB, offsetof(struct kvm_vcpu, arch.pspb));
+ DEFINE(VCPU_TFHAR, offsetof(struct kvm_vcpu, arch.tfhar));
+ DEFINE(VCPU_TFIAR, offsetof(struct kvm_vcpu, arch.tfiar));
+ DEFINE(VCPU_TEXASR, offsetof(struct kvm_vcpu, arch.texasr));
DEFINE(VCPU_EBBHR, offsetof(struct kvm_vcpu, arch.ebbhr));
DEFINE(VCPU_EBBRR, offsetof(struct kvm_vcpu, arch.ebbrr));
DEFINE(VCPU_BESCR, offsetof(struct kvm_vcpu, arch.bescr));
@@ -555,22 +558,6 @@ int main(void)
DEFINE(VCPU_SLB_E, offsetof(struct kvmppc_slb, orige));
DEFINE(VCPU_SLB_V, offsetof(struct kvmppc_slb, origv));
DEFINE(VCPU_SLB_SIZE, sizeof(struct kvmppc_slb));
-#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
- DEFINE(VCPU_TFHAR, offsetof(struct kvm_vcpu, arch.tfhar));
- DEFINE(VCPU_TFIAR, offsetof(struct kvm_vcpu, arch.tfiar));
- DEFINE(VCPU_TEXASR, offsetof(struct kvm_vcpu, arch.texasr));
- DEFINE(VCPU_GPR_TM, offsetof(struct kvm_vcpu, arch.gpr_tm));
- DEFINE(VCPU_FPRS_TM, offsetof(struct kvm_vcpu, arch.fp_tm.fpr));
- DEFINE(VCPU_VRS_TM, offsetof(struct kvm_vcpu, arch.vr_tm.vr));
- DEFINE(VCPU_VRSAVE_TM, offsetof(struct kvm_vcpu, arch.vrsave_tm));
- DEFINE(VCPU_CR_TM, offsetof(struct kvm_vcpu, arch.cr_tm));
- DEFINE(VCPU_LR_TM, offsetof(struct kvm_vcpu, arch.lr_tm));
- DEFINE(VCPU_CTR_TM, offsetof(struct kvm_vcpu, arch.ctr_tm));
- DEFINE(VCPU_AMR_TM, offsetof(struct kvm_vcpu, arch.amr_tm));
- DEFINE(VCPU_PPR_TM, offsetof(struct kvm_vcpu, arch.ppr_tm));
- DEFINE(VCPU_DSCR_TM, offsetof(struct kvm_vcpu, arch.dscr_tm));
- DEFINE(VCPU_TAR_TM, offsetof(struct kvm_vcpu, arch.tar_tm));
-#endif
#ifdef CONFIG_PPC_BOOK3S_64
#ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 3b498d942a22..71f2e8e6e7b1 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -879,7 +879,6 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
case KVM_REG_PPC_IAMR:
*val = get_reg_val(id, vcpu->arch.iamr);
break;
-#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
case KVM_REG_PPC_TFHAR:
*val = get_reg_val(id, vcpu->arch.tfhar);
break;
@@ -889,7 +888,6 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
case KVM_REG_PPC_TEXASR:
*val = get_reg_val(id, vcpu->arch.texasr);
break;
-#endif
case KVM_REG_PPC_FSCR:
*val = get_reg_val(id, vcpu->arch.fscr);
break;
@@ -1039,7 +1037,6 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
case KVM_REG_PPC_IAMR:
vcpu->arch.iamr = set_reg_val(id, *val);
break;
-#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
case KVM_REG_PPC_TFHAR:
vcpu->arch.tfhar = set_reg_val(id, *val);
break;
@@ -1049,7 +1046,6 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
case KVM_REG_PPC_TEXASR:
vcpu->arch.texasr = set_reg_val(id, *val);
break;
-#endif
case KVM_REG_PPC_FSCR:
vcpu->arch.fscr = set_reg_val(id, *val);
break;
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index e66d4ec04d95..557a47800ca1 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -704,15 +704,13 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
ld r6, VCPU_VTB(r4)
mtspr SPRN_IC, r5
mtspr SPRN_VTB, r6
-#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
ld r5, VCPU_TFHAR(r4)
ld r6, VCPU_TFIAR(r4)
ld r7, VCPU_TEXASR(r4)
+ ld r8, VCPU_EBBHR(r4)
mtspr SPRN_TFHAR, r5
mtspr SPRN_TFIAR, r6
mtspr SPRN_TEXASR, r7
-#endif
- ld r8, VCPU_EBBHR(r4)
mtspr SPRN_EBBHR, r8
ld r5, VCPU_EBBRR(r4)
ld r6, VCPU_BESCR(r4)
@@ -1122,15 +1120,13 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
std r5, VCPU_IC(r9)
std r6, VCPU_VTB(r9)
std r7, VCPU_TAR(r9)
-#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
mfspr r5, SPRN_TFHAR
mfspr r6, SPRN_TFIAR
mfspr r7, SPRN_TEXASR
+ mfspr r8, SPRN_EBBHR
std r5, VCPU_TFHAR(r9)
std r6, VCPU_TFIAR(r9)
std r7, VCPU_TEXASR(r9)
-#endif
- mfspr r8, SPRN_EBBHR
std r8, VCPU_EBBHR(r9)
mfspr r5, SPRN_EBBRR
mfspr r6, SPRN_BESCR
@@ -1504,73 +1500,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
1: addi r8,r8,16
.endr
- /* Save DEC */
- mfspr r5,SPRN_DEC
- mftb r6
- extsw r5,r5
- add r5,r5,r6
- std r5,VCPU_DEC_EXPIRES(r9)
-
-BEGIN_FTR_SECTION
- b 8f
-END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
- /* Turn on TM so we can access TFHAR/TFIAR/TEXASR */
- mfmsr r8
- li r0, 1
- rldimi r8, r0, MSR_TM_LG, 63-MSR_TM_LG
- mtmsrd r8
-
- /* Save POWER8-specific registers */
- mfspr r5, SPRN_IAMR
- mfspr r6, SPRN_PSPB
- mfspr r7, SPRN_FSCR
- std r5, VCPU_IAMR(r9)
- stw r6, VCPU_PSPB(r9)
- std r7, VCPU_FSCR(r9)
- mfspr r5, SPRN_IC
- mfspr r6, SPRN_VTB
- mfspr r7, SPRN_TAR
- std r5, VCPU_IC(r9)
- std r6, VCPU_VTB(r9)
- std r7, VCPU_TAR(r9)
-#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
- mfspr r5, SPRN_TFHAR
- mfspr r6, SPRN_TFIAR
- mfspr r7, SPRN_TEXASR
- std r5, VCPU_TFHAR(r9)
- std r6, VCPU_TFIAR(r9)
- std r7, VCPU_TEXASR(r9)
-#endif
- mfspr r8, SPRN_EBBHR
- std r8, VCPU_EBBHR(r9)
- mfspr r5, SPRN_EBBRR
- mfspr r6, SPRN_BESCR
- mfspr r7, SPRN_CSIGR
- mfspr r8, SPRN_TACR
- std r5, VCPU_EBBRR(r9)
- std r6, VCPU_BESCR(r9)
- std r7, VCPU_CSIGR(r9)
- std r8, VCPU_TACR(r9)
- mfspr r5, SPRN_TCSCR
- mfspr r6, SPRN_ACOP
- mfspr r7, SPRN_PID
- mfspr r8, SPRN_WORT
- std r5, VCPU_TCSCR(r9)
- std r6, VCPU_ACOP(r9)
- stw r7, VCPU_GUEST_PID(r9)
- std r8, VCPU_WORT(r9)
-8:
-
- /* Save and reset AMR and UAMOR before turning on the MMU */
-BEGIN_FTR_SECTION
- mfspr r5,SPRN_AMR
- mfspr r6,SPRN_UAMOR
- std r5,VCPU_AMR(r9)
- std r6,VCPU_UAMOR(r9)
- li r6,0
- mtspr SPRN_AMR,r6
-END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
-
/* Unset guest mode */
li r0, KVM_GUEST_MODE_NONE
stb r0, HSTATE_IN_GUEST(r13)
--
1.8.3.2
^ permalink raw reply related
* [PATCH 2/2] KVM: PPC: Book3S HV: Fix register usage when loading/saving VRSAVE
From: Aneesh Kumar K.V @ 2014-03-06 10:36 UTC (permalink / raw)
To: agraf, benh, paulus; +Cc: linuxppc-dev, kvm, kvm-ppc, Aneesh Kumar K.V
In-Reply-To: <1394102170-22126-1-git-send-email-aneesh.kumar@linux.vnet.ibm.com>
From: Paul Mackerras <paulus@samba.org>
Commit 595e4f7e697e ("KVM: PPC: Book3S HV: Use load/store_fp_state functions
in HV guest entry/exit") changed the register usage in kvmppc_save_fp() and
kvmppc_load_fp() but omitted changing the instructions that load and save VRSAVE.
The result is that the VRSAVE value was loaded from a constant address, and
saved to a location past the end of the vcpu struct, causing host kernel memory
corruption and various kinds of host kernel crashes.
This fixes the problem by using register r31, which contains the
vcpu pointer, instead of r3 and r4.
Signed-off-by: Paul Mackerras <paulus@samba.org>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
arch/powerpc/kvm/book3s_hv_rmhandlers.S | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index 557a47800ca1..6962d38c76f5 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -2132,7 +2132,7 @@ BEGIN_FTR_SECTION
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
#endif
mfspr r6,SPRN_VRSAVE
- stw r6,VCPU_VRSAVE(r3)
+ stw r6,VCPU_VRSAVE(r31)
mtlr r30
mtmsrd r5
isync
@@ -2169,7 +2169,7 @@ BEGIN_FTR_SECTION
bl .load_vr_state
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
#endif
- lwz r7,VCPU_VRSAVE(r4)
+ lwz r7,VCPU_VRSAVE(r31)
mtspr SPRN_VRSAVE,r7
mtlr r30
mr r4,r31
--
1.8.3.2
^ permalink raw reply related
* Re: [PATCH 2/3] dts: mpc512x: adjust clock specs for FEC nodes
From: Sascha Hauer @ 2014-03-06 10:21 UTC (permalink / raw)
To: Gerhard Sittig
Cc: Mark Rutland, devicetree, Anatolij Gustschin, Mike Turquette,
Pawel Moll, Ian Campbell, Rob Herring, Shawn Guo, linuxppc-dev,
linux-arm-kernel
In-Reply-To: <20140305105209.GZ3327@book.gsilab.sittig.org>
On Wed, Mar 05, 2014 at 11:52:09AM +0100, Gerhard Sittig wrote:
> On Wed, Mar 05, 2014 at 09:48 +0800, Shawn Guo wrote:
> >
> > On Mon, Mar 03, 2014 at 10:22:31AM +0100, Gerhard Sittig wrote:
> > > On Mon, Feb 24, 2014 at 11:25 +0100, Gerhard Sittig wrote:
> > > >
> > > > a recent FEC binding document update that was motivated by i.MX
> > > > development revealed that ARM and PowerPC implementations in Linux
> > > > did not agree on the clock names to use for the FEC nodes
> > > >
> > > > change clock names from "per" to "ipg" in the FEC nodes of the
> > > > mpc5121.dtsi include file such that the .dts specs comply with
> > > > the common FEC binding
> > > >
> > > > this "incompatible" change does not break operation, because
> > > > - COMMON_CLK support for MPC5121/23/25 and adjusted .dts files
> > > > were only introduced in Linux v3.14-rc1, no mainline release
> > > > provided these specs before
> > > > - if this change won't make it for v3.14, the MPC512x CCF support
> > > > provides full backwards compability, and keeps operating with
> > > > device trees which lack clock specs or don't match in the names
> > > >
> > > > Signed-off-by: Gerhard Sittig <gsi@denx.de>
> > >
> > > ping
> > >
> > > Are there opinions about making PowerPC users of FEC use the same
> > > clock names as ARM users do, to re-use (actually: keep sharing)
> > > the FEC binding? The alternative would be to fragment the FEC
> > > binding into several bindings for ARM and PowerPC, which I feel
> > > would be undesirable, and is not necessary.
> >
> > As I already said, Documentation/devicetree/bindings/net/fsl-fec.txt
> > was created specifically for i.MX FEC controller from day one. And even
> > as of today, it doesn't serve PowerPC, because for example the property
> > 'phy-mode' documented as required one is not required by PowerPC FEC.
> > My opinion would be to patch fsl-fec.txt a little bit to make it clear
> > that it's a binding doc for i.MX FEC, and create the other one for
> > PowerPC FEC. This is the way less confusing to people and easier for
> > binding maintenance.
>
> Should we still try to have a common behaviour where possible?
> Such that even if there are two bindings, they don't diverge in
> "unnecessary" ways?
Maybe the long term goal should be to share the code. The MPC5200 FEC
and the i.MX FEC are very similar. Only the DMA engine is quite
different.
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply
* Re: [PATCH 1/2] Revert "KVM: PPC: Book3S HV: Add new state for transactional memory"
From: Paul Mackerras @ 2014-03-06 11:18 UTC (permalink / raw)
To: Aneesh Kumar K.V; +Cc: Michael Neuling, kvm, agraf, kvm-ppc, linuxppc-dev
In-Reply-To: <1394102170-22126-1-git-send-email-aneesh.kumar@linux.vnet.ibm.com>
On Thu, Mar 06, 2014 at 04:06:09PM +0530, Aneesh Kumar K.V wrote:
> From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
>
> This reverts commit 7b490411c37f7ab7965cbdfe5e3ec28eadb6db5b which cause
> the below crash in the host.
>
> Unable to handle kernel paging request for data at address 0xf00000001223f278
> Faulting instruction address: 0xc000000000202a00
Why exactly does it cause that crash? What is the actual problem here?
Under what specific circumstances do you see the crash?
> cpu 0x30: Vector: 300 (Data Access) at [c000001e4debb2d0]
> pc: c000000000202a00: .kfree+0x40/0x200
> lr: c000000000098338: .kvmppc_core_destroy_vm_hv+0x38/0x90
> sp: c000001e4debb550
> msr: 9000000000009032
> dar: f00000001223f278
> dsisr: 40000000
> current = 0xc000001e4de195c0
> paca = 0xc00000000fefb000 softe: 0 irq_happened: 0x01
> pid = 29379, comm = qemu-system-ppc
> enter ? for help
> [c000001e4debb5e0] c000000000098338 .kvmppc_core_destroy_vm_hv+0x38/0x90
> [c000001e4debb670] c000000000087f80 .kvmppc_core_destroy_vm+0x30/0x70
> [c000001e4debb6f0] c000000000084f28 .kvm_arch_destroy_vm+0xd8/0x120
> [c000001e4debb780] c000000000080218 .kvm_put_kvm+0x198/0x2e0
> [c000001e4debb820] c0000000000880d4 .kvm_spapr_tce_release+0xe4/0x110
> [c000001e4debb8b0] c000000000218578 .__fput+0xb8/0x2a0
> [c000001e4debb950] c0000000000d9af4 .task_work_run+0x114/0x150
> [c000001e4debb9f0] c0000000000b31e8 .do_exit+0x328/0xbc0
> [c000001e4debbae0] c0000000000b4cd4 .do_group_exit+0x54/0xf0
> [c000001e4debbb70] c0000000000c8448 .get_signal_to_deliver+0x1e8/0x6f0
> [c000001e4debbc70] c000000000017ee4 .do_signal+0x54/0x320
> [c000001e4debbdb0] c0000000000182e8 .do_notify_resume+0x68/0x80
> [c000001e4debbe30] c00000000000a7b0 .ret_from_except_lite+0x5c/0x60
> --- Exception: c00 (System Call) at 00003fffb38a4744
> SP (3ffd36ffe360) is in userspace
> 30:mon> zr
>
> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
> ---
> arch/powerpc/include/asm/kvm_host.h | 24 ++---------
> arch/powerpc/kernel/asm-offsets.c | 19 ++-------
> arch/powerpc/kvm/book3s_hv.c | 4 --
> arch/powerpc/kvm/book3s_hv_rmhandlers.S | 75 +--------------------------------
> 4 files changed, 8 insertions(+), 114 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
> index 1eaea2dea174..7726a3bc8ff0 100644
> --- a/arch/powerpc/include/asm/kvm_host.h
> +++ b/arch/powerpc/include/asm/kvm_host.h
> @@ -475,6 +475,9 @@ struct kvm_vcpu_arch {
> ulong ppr;
> ulong pspb;
> ulong fscr;
> + ulong tfhar;
> + ulong tfiar;
> + ulong texasr;
> ulong ebbhr;
> ulong ebbrr;
> ulong bescr;
> @@ -523,27 +526,6 @@ struct kvm_vcpu_arch {
> u64 siar;
> u64 sdar;
> u64 sier;
> -#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
> - u64 tfhar;
> - u64 texasr;
> - u64 tfiar;
> -
> - u32 cr_tm;
> - u64 lr_tm;
> - u64 ctr_tm;
> - u64 amr_tm;
> - u64 ppr_tm;
> - u64 dscr_tm;
> - u64 tar_tm;
> -
> - ulong gpr_tm[32];
> -
> - struct thread_fp_state fp_tm;
> -
> - struct thread_vr_state vr_tm;
> - u32 vrsave_tm; /* also USPRG0 */
> -
> -#endif
>
> #ifdef CONFIG_KVM_EXIT_TIMING
> struct mutex exit_timing_lock;
> diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
> index b5aacf72ae6f..936d445b961a 100644
> --- a/arch/powerpc/kernel/asm-offsets.c
> +++ b/arch/powerpc/kernel/asm-offsets.c
> @@ -534,6 +534,9 @@ int main(void)
> DEFINE(VCPU_PPR, offsetof(struct kvm_vcpu, arch.ppr));
> DEFINE(VCPU_FSCR, offsetof(struct kvm_vcpu, arch.fscr));
> DEFINE(VCPU_PSPB, offsetof(struct kvm_vcpu, arch.pspb));
> + DEFINE(VCPU_TFHAR, offsetof(struct kvm_vcpu, arch.tfhar));
> + DEFINE(VCPU_TFIAR, offsetof(struct kvm_vcpu, arch.tfiar));
> + DEFINE(VCPU_TEXASR, offsetof(struct kvm_vcpu, arch.texasr));
> DEFINE(VCPU_EBBHR, offsetof(struct kvm_vcpu, arch.ebbhr));
> DEFINE(VCPU_EBBRR, offsetof(struct kvm_vcpu, arch.ebbrr));
> DEFINE(VCPU_BESCR, offsetof(struct kvm_vcpu, arch.bescr));
> @@ -555,22 +558,6 @@ int main(void)
> DEFINE(VCPU_SLB_E, offsetof(struct kvmppc_slb, orige));
> DEFINE(VCPU_SLB_V, offsetof(struct kvmppc_slb, origv));
> DEFINE(VCPU_SLB_SIZE, sizeof(struct kvmppc_slb));
> -#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
> - DEFINE(VCPU_TFHAR, offsetof(struct kvm_vcpu, arch.tfhar));
> - DEFINE(VCPU_TFIAR, offsetof(struct kvm_vcpu, arch.tfiar));
> - DEFINE(VCPU_TEXASR, offsetof(struct kvm_vcpu, arch.texasr));
> - DEFINE(VCPU_GPR_TM, offsetof(struct kvm_vcpu, arch.gpr_tm));
> - DEFINE(VCPU_FPRS_TM, offsetof(struct kvm_vcpu, arch.fp_tm.fpr));
> - DEFINE(VCPU_VRS_TM, offsetof(struct kvm_vcpu, arch.vr_tm.vr));
> - DEFINE(VCPU_VRSAVE_TM, offsetof(struct kvm_vcpu, arch.vrsave_tm));
> - DEFINE(VCPU_CR_TM, offsetof(struct kvm_vcpu, arch.cr_tm));
> - DEFINE(VCPU_LR_TM, offsetof(struct kvm_vcpu, arch.lr_tm));
> - DEFINE(VCPU_CTR_TM, offsetof(struct kvm_vcpu, arch.ctr_tm));
> - DEFINE(VCPU_AMR_TM, offsetof(struct kvm_vcpu, arch.amr_tm));
> - DEFINE(VCPU_PPR_TM, offsetof(struct kvm_vcpu, arch.ppr_tm));
> - DEFINE(VCPU_DSCR_TM, offsetof(struct kvm_vcpu, arch.dscr_tm));
> - DEFINE(VCPU_TAR_TM, offsetof(struct kvm_vcpu, arch.tar_tm));
> -#endif
>
> #ifdef CONFIG_PPC_BOOK3S_64
> #ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE
> diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
> index 3b498d942a22..71f2e8e6e7b1 100644
> --- a/arch/powerpc/kvm/book3s_hv.c
> +++ b/arch/powerpc/kvm/book3s_hv.c
> @@ -879,7 +879,6 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
> case KVM_REG_PPC_IAMR:
> *val = get_reg_val(id, vcpu->arch.iamr);
> break;
> -#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
> case KVM_REG_PPC_TFHAR:
> *val = get_reg_val(id, vcpu->arch.tfhar);
> break;
> @@ -889,7 +888,6 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
> case KVM_REG_PPC_TEXASR:
> *val = get_reg_val(id, vcpu->arch.texasr);
> break;
> -#endif
> case KVM_REG_PPC_FSCR:
> *val = get_reg_val(id, vcpu->arch.fscr);
> break;
> @@ -1039,7 +1037,6 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
> case KVM_REG_PPC_IAMR:
> vcpu->arch.iamr = set_reg_val(id, *val);
> break;
> -#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
> case KVM_REG_PPC_TFHAR:
> vcpu->arch.tfhar = set_reg_val(id, *val);
> break;
> @@ -1049,7 +1046,6 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
> case KVM_REG_PPC_TEXASR:
> vcpu->arch.texasr = set_reg_val(id, *val);
> break;
> -#endif
> case KVM_REG_PPC_FSCR:
> vcpu->arch.fscr = set_reg_val(id, *val);
> break;
> diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
> index e66d4ec04d95..557a47800ca1 100644
> --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
> +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
> @@ -704,15 +704,13 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
> ld r6, VCPU_VTB(r4)
> mtspr SPRN_IC, r5
> mtspr SPRN_VTB, r6
> -#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
> ld r5, VCPU_TFHAR(r4)
> ld r6, VCPU_TFIAR(r4)
> ld r7, VCPU_TEXASR(r4)
> + ld r8, VCPU_EBBHR(r4)
> mtspr SPRN_TFHAR, r5
> mtspr SPRN_TFIAR, r6
> mtspr SPRN_TEXASR, r7
> -#endif
> - ld r8, VCPU_EBBHR(r4)
> mtspr SPRN_EBBHR, r8
> ld r5, VCPU_EBBRR(r4)
> ld r6, VCPU_BESCR(r4)
> @@ -1122,15 +1120,13 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
> std r5, VCPU_IC(r9)
> std r6, VCPU_VTB(r9)
> std r7, VCPU_TAR(r9)
> -#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
> mfspr r5, SPRN_TFHAR
> mfspr r6, SPRN_TFIAR
> mfspr r7, SPRN_TEXASR
> + mfspr r8, SPRN_EBBHR
> std r5, VCPU_TFHAR(r9)
> std r6, VCPU_TFIAR(r9)
> std r7, VCPU_TEXASR(r9)
> -#endif
> - mfspr r8, SPRN_EBBHR
> std r8, VCPU_EBBHR(r9)
> mfspr r5, SPRN_EBBRR
> mfspr r6, SPRN_BESCR
> @@ -1504,73 +1500,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
> 1: addi r8,r8,16
> .endr
>
> - /* Save DEC */
> - mfspr r5,SPRN_DEC
> - mftb r6
> - extsw r5,r5
> - add r5,r5,r6
> - std r5,VCPU_DEC_EXPIRES(r9)
> -
> -BEGIN_FTR_SECTION
> - b 8f
> -END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
> - /* Turn on TM so we can access TFHAR/TFIAR/TEXASR */
> - mfmsr r8
> - li r0, 1
> - rldimi r8, r0, MSR_TM_LG, 63-MSR_TM_LG
> - mtmsrd r8
> -
> - /* Save POWER8-specific registers */
> - mfspr r5, SPRN_IAMR
> - mfspr r6, SPRN_PSPB
> - mfspr r7, SPRN_FSCR
> - std r5, VCPU_IAMR(r9)
> - stw r6, VCPU_PSPB(r9)
> - std r7, VCPU_FSCR(r9)
> - mfspr r5, SPRN_IC
> - mfspr r6, SPRN_VTB
> - mfspr r7, SPRN_TAR
> - std r5, VCPU_IC(r9)
> - std r6, VCPU_VTB(r9)
> - std r7, VCPU_TAR(r9)
> -#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
> - mfspr r5, SPRN_TFHAR
> - mfspr r6, SPRN_TFIAR
> - mfspr r7, SPRN_TEXASR
> - std r5, VCPU_TFHAR(r9)
> - std r6, VCPU_TFIAR(r9)
> - std r7, VCPU_TEXASR(r9)
> -#endif
> - mfspr r8, SPRN_EBBHR
> - std r8, VCPU_EBBHR(r9)
> - mfspr r5, SPRN_EBBRR
> - mfspr r6, SPRN_BESCR
> - mfspr r7, SPRN_CSIGR
> - mfspr r8, SPRN_TACR
> - std r5, VCPU_EBBRR(r9)
> - std r6, VCPU_BESCR(r9)
> - std r7, VCPU_CSIGR(r9)
> - std r8, VCPU_TACR(r9)
> - mfspr r5, SPRN_TCSCR
> - mfspr r6, SPRN_ACOP
> - mfspr r7, SPRN_PID
> - mfspr r8, SPRN_WORT
> - std r5, VCPU_TCSCR(r9)
> - std r6, VCPU_ACOP(r9)
> - stw r7, VCPU_GUEST_PID(r9)
> - std r8, VCPU_WORT(r9)
> -8:
> -
> - /* Save and reset AMR and UAMOR before turning on the MMU */
> -BEGIN_FTR_SECTION
> - mfspr r5,SPRN_AMR
> - mfspr r6,SPRN_UAMOR
> - std r5,VCPU_AMR(r9)
> - std r6,VCPU_UAMOR(r9)
> - li r6,0
> - mtspr SPRN_AMR,r6
> -END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
> -
> /* Unset guest mode */
> li r0, KVM_GUEST_MODE_NONE
> stb r0, HSTATE_IN_GUEST(r13)
> --
> 1.8.3.2
Paul.
^ permalink raw reply
* Re: [PATCH 3/3] perf: Use 64-bit value when comparing sample_regs
From: Gabriel Paubert @ 2014-03-06 11:33 UTC (permalink / raw)
To: David Laight
Cc: Michael Ellerman, linux-kernel@vger.kernel.org, Stephane Eranian,
linuxppc-dev@ozlabs.org, Paul Mackerras, Arnaldo Carvalho de Melo,
'Sukadev Bhattiprolu', Jiri Olsa
In-Reply-To: <063D6719AE5E284EB5DD2968C1650D6D0F6D3983@AcuExch.aculab.com>
On Thu, Mar 06, 2014 at 09:44:47AM +0000, David Laight wrote:
> From: Sukadev Bhattiprolu
> > When checking whether a bit representing a register is set in
> > sample_regs, a 64-bit mask, use 64-bit value (1LL).
> >
> > Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
> > ---
> > tools/perf/util/unwind.c | 4 ++--
> > 1 file changed, 2 insertions(+), 2 deletions(-)
> >
> > diff --git a/tools/perf/util/unwind.c b/tools/perf/util/unwind.c
> > index 742f23b..2b888c6 100644
> > --- a/tools/perf/util/unwind.c
> > +++ b/tools/perf/util/unwind.c
> > @@ -396,11 +396,11 @@ static int reg_value(unw_word_t *valp, struct regs_dump *regs, int id,
> > {
> > int i, idx = 0;
> >
> > - if (!(sample_regs & (1 << id)))
> > + if (!(sample_regs & (1LL << id)))
> > return -EINVAL;
> >
> > for (i = 0; i < id; i++) {
> > - if (sample_regs & (1 << i))
> > + if (sample_regs & (1LL << i))
> > idx++;
> > }
>
> There are much faster ways to count the number of set bits, especially
> if you might need to check a significant number of bits.
> There might even be a function defined somewhere to do it.
Indeed, look for Hamming weight (hweight family of functions)
in asm/hweight.h and what is included from there.
Besides that, many modern processors also have a machine instruction
to perform this task. In the processor manuals the instruction is
described as population count and the mnemonic starts with "popcnt"
on x86 and ppc.
Gabriel
> Basically you just add up the bits, for 16 bit it would be:
> val = (val & 0x5555) + (val >> 1) & 0x5555;
> val = (val & 0x3333) + (val >> 2) & 0x3333;
> val = (val & 0x0f0f) + (val >> 4) & 0x0f0f;
> val = (val & 0x00ff) + (val >> 8) & 0x00ff;
> As the size of the work increases the improvement is more significant.
> (Some of the later masking can probably be proven unnecessary.)
>
> David
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
^ permalink raw reply
* Re: [PATCH 1/2] Revert "KVM: PPC: Book3S HV: Add new state for transactional memory"
From: Aneesh Kumar K.V @ 2014-03-06 13:29 UTC (permalink / raw)
To: Paul Mackerras; +Cc: Michael Neuling, kvm, agraf, kvm-ppc, linuxppc-dev
In-Reply-To: <20140306111836.GA5729@iris.ozlabs.ibm.com>
Paul Mackerras <paulus@samba.org> writes:
> On Thu, Mar 06, 2014 at 04:06:09PM +0530, Aneesh Kumar K.V wrote:
>> From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
>>
>> This reverts commit 7b490411c37f7ab7965cbdfe5e3ec28eadb6db5b which cause
>> the below crash in the host.
>>
>> Unable to handle kernel paging request for data at address 0xf00000001223f278
>> Faulting instruction address: 0xc000000000202a00
>
> Why exactly does it cause that crash? What is the actual problem here?
> Under what specific circumstances do you see the crash?
When we exit from guest, we find that 263 index in the
kvm->arch.vcore is always corrupted. The way to reproduce is to start
the guest and use Qemu monitor to quit. That will result in the below
crash.
Now the commit in 7b490411c37f7ab7965cbdfe5e3ec28eadb6db5b is not
complete. If you look at series
http://article.gmane.org/gmane.comp.emulators.kvm.powerpc.devel/8562
Andreas didn't pull all the changes because TM changes had issues like
http://article.gmane.org/gmane.comp.emulators.kvm.devel/118411
+<<<<<<< HEAD
+=======
+ /* Save DEC */
+ mfspr r5,SPRN_DEC
+ mftb r6
+ extsw r5,r5
+ add r5,r5,r6
+ std r5,VCPU_DEC_EXPIRES(r9)
+
and
+ /* Save and reset AMR and UAMOR before turning on the MMU */
+BEGIN_FTR_SECTION
+ mfspr r5,SPRN_AMR
+ mfspr r6,SPRN_UAMOR
+ std r5,VCPU_AMR(r9)
+ std r6,VCPU_UAMOR(r9)
+ li r6,0
+ mtspr SPRN_AMR,r6
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
+
+>>>>>>> a65ae5a... KVM: PPC: Book3S HV: Add new state for transactional memory
Which got reverted in the next patch
http://article.gmane.org/gmane.comp.emulators.kvm.powerpc.devel/8571
-<<<<<<< HEAD
-=======
- /* Save DEC */
- mfspr r5,SPRN_DEC
- mftb r6
- extsw r5,r5
- add r5,r5,r6
- std r5,VCPU_DEC_EXPIRES(r9)
-
-BEGIN_FTR_SECTION
and
-
- /* Save and reset AMR and UAMOR before turning on the MMU */
-BEGIN_FTR_SECTION
- mfspr r5,SPRN_AMR
- mfspr r6,SPRN_UAMOR
- std r5,VCPU_AMR(r9)
- std r6,VCPU_UAMOR(r9)
- li r6,0
- mtspr SPRN_AMR,r6
-END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
-
->>>>>>> a65ae5a... KVM: PPC: Book3S HV: Add new state for transactional memory
I guess the complete series will possibly work. But since we dropped
patch 16 and 17 we ended up with broken code
http://article.gmane.org/gmane.comp.emulators.kvm.powerpc.devel/8667
Hence the idea that we will revert TM stuff for 3.14 and do it properly
for 3.15 ?
>
>> cpu 0x30: Vector: 300 (Data Access) at [c000001e4debb2d0]
>> pc: c000000000202a00: .kfree+0x40/0x200
>> lr: c000000000098338: .kvmppc_core_destroy_vm_hv+0x38/0x90
>> sp: c000001e4debb550
>> msr: 9000000000009032
>> dar: f00000001223f278
>> dsisr: 40000000
>> current = 0xc000001e4de195c0
>> paca = 0xc00000000fefb000 softe: 0 irq_happened: 0x01
>> pid = 29379, comm = qemu-system-ppc
>> enter ? for help
>> [c000001e4debb5e0] c000000000098338 .kvmppc_core_destroy_vm_hv+0x38/0x90
>> [c000001e4debb670] c000000000087f80 .kvmppc_core_destroy_vm+0x30/0x70
>> [c000001e4debb6f0] c000000000084f28 .kvm_arch_destroy_vm+0xd8/0x120
>> [c000001e4debb780] c000000000080218 .kvm_put_kvm+0x198/0x2e0
>> [c000001e4debb820] c0000000000880d4 .kvm_spapr_tce_release+0xe4/0x110
>> [c000001e4debb8b0] c000000000218578 .__fput+0xb8/0x2a0
>> [c000001e4debb950] c0000000000d9af4 .task_work_run+0x114/0x150
>> [c000001e4debb9f0] c0000000000b31e8 .do_exit+0x328/0xbc0
>> [c000001e4debbae0] c0000000000b4cd4 .do_group_exit+0x54/0xf0
>> [c000001e4debbb70] c0000000000c8448 .get_signal_to_deliver+0x1e8/0x6f0
>> [c000001e4debbc70] c000000000017ee4 .do_signal+0x54/0x320
>> [c000001e4debbdb0] c0000000000182e8 .do_notify_resume+0x68/0x80
>> [c000001e4debbe30] c00000000000a7b0 .ret_from_except_lite+0x5c/0x60
>> --- Exception: c00 (System Call) at 00003fffb38a4744
>> SP (3ffd36ffe360) is in userspace
>> 30:mon> zr
>>
>> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
>> ---
>> arch/powerpc/include/asm/kvm_host.h | 24 ++---------
>> arch/powerpc/kernel/asm-offsets.c | 19 ++-------
>> arch/powerpc/kvm/book3s_hv.c | 4 --
>> arch/powerpc/kvm/book3s_hv_rmhandlers.S | 75 +--------------------------------
>> 4 files changed, 8 insertions(+), 114 deletions(-)
>>
>> diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
>> index 1eaea2dea174..7726a3bc8ff0 100644
>> --- a/arch/powerpc/include/asm/kvm_host.h
>> +++ b/arch/powerpc/include/asm/kvm_host.h
>> @@ -475,6 +475,9 @@ struct kvm_vcpu_arch {
>> ulong ppr;
>> ulong pspb;
>> ulong fscr;
>> + ulong tfhar;
>> + ulong tfiar;
>> + ulong texasr;
>> ulong ebbhr;
>> ulong ebbrr;
>> ulong bescr;
>> @@ -523,27 +526,6 @@ struct kvm_vcpu_arch {
>> u64 siar;
>> u64 sdar;
>> u64 sier;
>> -#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
>> - u64 tfhar;
>> - u64 texasr;
>> - u64 tfiar;
>> -
>> - u32 cr_tm;
>> - u64 lr_tm;
>> - u64 ctr_tm;
>> - u64 amr_tm;
>> - u64 ppr_tm;
>> - u64 dscr_tm;
>> - u64 tar_tm;
>> -
>> - ulong gpr_tm[32];
>> -
>> - struct thread_fp_state fp_tm;
>> -
>> - struct thread_vr_state vr_tm;
>> - u32 vrsave_tm; /* also USPRG0 */
>> -
>> -#endif
>>
>> #ifdef CONFIG_KVM_EXIT_TIMING
>> struct mutex exit_timing_lock;
>> diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
>> index b5aacf72ae6f..936d445b961a 100644
>> --- a/arch/powerpc/kernel/asm-offsets.c
>> +++ b/arch/powerpc/kernel/asm-offsets.c
>> @@ -534,6 +534,9 @@ int main(void)
>> DEFINE(VCPU_PPR, offsetof(struct kvm_vcpu, arch.ppr));
>> DEFINE(VCPU_FSCR, offsetof(struct kvm_vcpu, arch.fscr));
>> DEFINE(VCPU_PSPB, offsetof(struct kvm_vcpu, arch.pspb));
>> + DEFINE(VCPU_TFHAR, offsetof(struct kvm_vcpu, arch.tfhar));
>> + DEFINE(VCPU_TFIAR, offsetof(struct kvm_vcpu, arch.tfiar));
>> + DEFINE(VCPU_TEXASR, offsetof(struct kvm_vcpu, arch.texasr));
>> DEFINE(VCPU_EBBHR, offsetof(struct kvm_vcpu, arch.ebbhr));
>> DEFINE(VCPU_EBBRR, offsetof(struct kvm_vcpu, arch.ebbrr));
>> DEFINE(VCPU_BESCR, offsetof(struct kvm_vcpu, arch.bescr));
>> @@ -555,22 +558,6 @@ int main(void)
>> DEFINE(VCPU_SLB_E, offsetof(struct kvmppc_slb, orige));
>> DEFINE(VCPU_SLB_V, offsetof(struct kvmppc_slb, origv));
>> DEFINE(VCPU_SLB_SIZE, sizeof(struct kvmppc_slb));
>> -#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
>> - DEFINE(VCPU_TFHAR, offsetof(struct kvm_vcpu, arch.tfhar));
>> - DEFINE(VCPU_TFIAR, offsetof(struct kvm_vcpu, arch.tfiar));
>> - DEFINE(VCPU_TEXASR, offsetof(struct kvm_vcpu, arch.texasr));
>> - DEFINE(VCPU_GPR_TM, offsetof(struct kvm_vcpu, arch.gpr_tm));
>> - DEFINE(VCPU_FPRS_TM, offsetof(struct kvm_vcpu, arch.fp_tm.fpr));
>> - DEFINE(VCPU_VRS_TM, offsetof(struct kvm_vcpu, arch.vr_tm.vr));
>> - DEFINE(VCPU_VRSAVE_TM, offsetof(struct kvm_vcpu, arch.vrsave_tm));
>> - DEFINE(VCPU_CR_TM, offsetof(struct kvm_vcpu, arch.cr_tm));
>> - DEFINE(VCPU_LR_TM, offsetof(struct kvm_vcpu, arch.lr_tm));
>> - DEFINE(VCPU_CTR_TM, offsetof(struct kvm_vcpu, arch.ctr_tm));
>> - DEFINE(VCPU_AMR_TM, offsetof(struct kvm_vcpu, arch.amr_tm));
>> - DEFINE(VCPU_PPR_TM, offsetof(struct kvm_vcpu, arch.ppr_tm));
>> - DEFINE(VCPU_DSCR_TM, offsetof(struct kvm_vcpu, arch.dscr_tm));
>> - DEFINE(VCPU_TAR_TM, offsetof(struct kvm_vcpu, arch.tar_tm));
>> -#endif
>>
>> #ifdef CONFIG_PPC_BOOK3S_64
>> #ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE
>> diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
>> index 3b498d942a22..71f2e8e6e7b1 100644
>> --- a/arch/powerpc/kvm/book3s_hv.c
>> +++ b/arch/powerpc/kvm/book3s_hv.c
>> @@ -879,7 +879,6 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
>> case KVM_REG_PPC_IAMR:
>> *val = get_reg_val(id, vcpu->arch.iamr);
>> break;
>> -#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
>> case KVM_REG_PPC_TFHAR:
>> *val = get_reg_val(id, vcpu->arch.tfhar);
>> break;
>> @@ -889,7 +888,6 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
>> case KVM_REG_PPC_TEXASR:
>> *val = get_reg_val(id, vcpu->arch.texasr);
>> break;
>> -#endif
>> case KVM_REG_PPC_FSCR:
>> *val = get_reg_val(id, vcpu->arch.fscr);
>> break;
>> @@ -1039,7 +1037,6 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
>> case KVM_REG_PPC_IAMR:
>> vcpu->arch.iamr = set_reg_val(id, *val);
>> break;
>> -#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
>> case KVM_REG_PPC_TFHAR:
>> vcpu->arch.tfhar = set_reg_val(id, *val);
>> break;
>> @@ -1049,7 +1046,6 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
>> case KVM_REG_PPC_TEXASR:
>> vcpu->arch.texasr = set_reg_val(id, *val);
>> break;
>> -#endif
>> case KVM_REG_PPC_FSCR:
>> vcpu->arch.fscr = set_reg_val(id, *val);
>> break;
>> diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
>> index e66d4ec04d95..557a47800ca1 100644
>> --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
>> +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
>> @@ -704,15 +704,13 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
>> ld r6, VCPU_VTB(r4)
>> mtspr SPRN_IC, r5
>> mtspr SPRN_VTB, r6
>> -#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
>> ld r5, VCPU_TFHAR(r4)
>> ld r6, VCPU_TFIAR(r4)
>> ld r7, VCPU_TEXASR(r4)
>> + ld r8, VCPU_EBBHR(r4)
>> mtspr SPRN_TFHAR, r5
>> mtspr SPRN_TFIAR, r6
>> mtspr SPRN_TEXASR, r7
>> -#endif
>> - ld r8, VCPU_EBBHR(r4)
>> mtspr SPRN_EBBHR, r8
>> ld r5, VCPU_EBBRR(r4)
>> ld r6, VCPU_BESCR(r4)
>> @@ -1122,15 +1120,13 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
>> std r5, VCPU_IC(r9)
>> std r6, VCPU_VTB(r9)
>> std r7, VCPU_TAR(r9)
>> -#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
>> mfspr r5, SPRN_TFHAR
>> mfspr r6, SPRN_TFIAR
>> mfspr r7, SPRN_TEXASR
>> + mfspr r8, SPRN_EBBHR
>> std r5, VCPU_TFHAR(r9)
>> std r6, VCPU_TFIAR(r9)
>> std r7, VCPU_TEXASR(r9)
>> -#endif
>> - mfspr r8, SPRN_EBBHR
>> std r8, VCPU_EBBHR(r9)
>> mfspr r5, SPRN_EBBRR
>> mfspr r6, SPRN_BESCR
>> @@ -1504,73 +1500,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
>> 1: addi r8,r8,16
>> .endr
>>
>> - /* Save DEC */
>> - mfspr r5,SPRN_DEC
>> - mftb r6
>> - extsw r5,r5
>> - add r5,r5,r6
>> - std r5,VCPU_DEC_EXPIRES(r9)
>> -
>> -BEGIN_FTR_SECTION
>> - b 8f
>> -END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
>> - /* Turn on TM so we can access TFHAR/TFIAR/TEXASR */
>> - mfmsr r8
>> - li r0, 1
>> - rldimi r8, r0, MSR_TM_LG, 63-MSR_TM_LG
>> - mtmsrd r8
>> -
>> - /* Save POWER8-specific registers */
>> - mfspr r5, SPRN_IAMR
>> - mfspr r6, SPRN_PSPB
>> - mfspr r7, SPRN_FSCR
>> - std r5, VCPU_IAMR(r9)
>> - stw r6, VCPU_PSPB(r9)
>> - std r7, VCPU_FSCR(r9)
>> - mfspr r5, SPRN_IC
>> - mfspr r6, SPRN_VTB
>> - mfspr r7, SPRN_TAR
>> - std r5, VCPU_IC(r9)
>> - std r6, VCPU_VTB(r9)
>> - std r7, VCPU_TAR(r9)
>> -#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
>> - mfspr r5, SPRN_TFHAR
>> - mfspr r6, SPRN_TFIAR
>> - mfspr r7, SPRN_TEXASR
>> - std r5, VCPU_TFHAR(r9)
>> - std r6, VCPU_TFIAR(r9)
>> - std r7, VCPU_TEXASR(r9)
>> -#endif
>> - mfspr r8, SPRN_EBBHR
>> - std r8, VCPU_EBBHR(r9)
>> - mfspr r5, SPRN_EBBRR
>> - mfspr r6, SPRN_BESCR
>> - mfspr r7, SPRN_CSIGR
>> - mfspr r8, SPRN_TACR
>> - std r5, VCPU_EBBRR(r9)
>> - std r6, VCPU_BESCR(r9)
>> - std r7, VCPU_CSIGR(r9)
>> - std r8, VCPU_TACR(r9)
>> - mfspr r5, SPRN_TCSCR
>> - mfspr r6, SPRN_ACOP
>> - mfspr r7, SPRN_PID
>> - mfspr r8, SPRN_WORT
>> - std r5, VCPU_TCSCR(r9)
>> - std r6, VCPU_ACOP(r9)
>> - stw r7, VCPU_GUEST_PID(r9)
>> - std r8, VCPU_WORT(r9)
>> -8:
>> -
>> - /* Save and reset AMR and UAMOR before turning on the MMU */
>> -BEGIN_FTR_SECTION
>> - mfspr r5,SPRN_AMR
>> - mfspr r6,SPRN_UAMOR
>> - std r5,VCPU_AMR(r9)
>> - std r6,VCPU_UAMOR(r9)
>> - li r6,0
>> - mtspr SPRN_AMR,r6
>> -END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
>> -
>> /* Unset guest mode */
>> li r0, KVM_GUEST_MODE_NONE
>> stb r0, HSTATE_IN_GUEST(r13)
>> --
>> 1.8.3.2
>
-aneesh
^ permalink raw reply
* Re: [PATCH RFC v8 5/5] dma: mpc512x: register for device tree channel lookup
From: Alexander Popov @ 2014-03-06 14:28 UTC (permalink / raw)
To: Andy Shevchenko
Cc: devicetree, Lars-Peter Clausen, Arnd Bergmann, Vinod Koul,
Gerhard Sittig, Alexander Popov, dmaengine, Dan Williams,
Anatolij Gustschin, linuxppc-dev
In-Reply-To: <1393247295.28803.10.camel@smile.fi.intel.com>
Hello Andy.
2014-02-24 17:08 GMT+04:00 Andy Shevchenko <andriy.shevchenko@linux.intel.com>:
> On Mon, 2014-02-24 at 15:09 +0400, Alexander Popov wrote:
>> @@ -1018,11 +1019,23 @@ static int mpc_dma_probe(struct platform_device *op)
>> /* Register DMA engine */
>> dev_set_drvdata(dev, mdma);
>> retval = dma_async_device_register(dma);
>> - if (retval) {
>> - devm_free_irq(dev, mdma->irq, mdma);
>> - irq_dispose_mapping(mdma->irq);
>> + if (retval)
>> + goto out_irq;
>> +
>> + /* register with OF helpers for DMA lookups (nonfatal) */
>> + if (dev->of_node) {
>> + retval = of_dma_controller_register(dev->of_node,
>> + of_dma_xlate_by_chan_id,
>> + mdma);
>> + if (retval)
>> + dev_warn(dev, "could not register for OF lookup\n");
>> }
>>
>> + return 0;
>> +
>> +out_irq:
>> + devm_free_irq(dev, mdma->irq, mdma);
>
> Something wrong either with devm_request_irq() or you don't need to call
> devm_free_irq() explicitly. Once we already try to discuss this earlier
> in this mailing list with Lars-Peter(?), though there were no solution
> how to keep devm_*_irq usability.
Thanks, I've read this discussion. It seems that the current code doesn't do
anything bad, though devm_request_irq() and devm_free_irq() can be changed
to request_irq() and free_irq() accordingly. Do you think it's worth being done
in a separate patch in this series?
>> + irq_dispose_mapping(mdma->irq);
>> return retval;
>> }
>>
>> @@ -1031,6 +1044,8 @@ static int mpc_dma_remove(struct platform_device *op)
>> struct device *dev = &op->dev;
>> struct mpc_dma *mdma = dev_get_drvdata(dev);
>>
>> + if (dev->of_node)
>> + of_dma_controller_free(dev->of_node);
>> dma_async_device_unregister(&mdma->dma);
>> devm_free_irq(dev, mdma->irq, mdma);
>> irq_dispose_mapping(mdma->irq);
Best regards,
Alexander
^ permalink raw reply
* [PATCH] kexec/powerpc: fix exporting memory limit
From: Nikita Yushchenko @ 2014-03-06 14:24 UTC (permalink / raw)
To: kexec, Benjamin Herrenschmidt, Paul Mackerras, Anton Blanchard,
Hari Bathini, Mahesh Salgaonkar, linuxppc-dev
Cc: yadviga, nyushchenko, lugovskoy, linux-kernel
When preparing dump-capturing kernel, kexec userspace tool needs to know
actual amount of memory used by the running kernel. This may differ from
extire available DRAM for a couple of reasons. To address this issue,
kdump kernel support code injects several attributes into device tree that
are later captured by userspace kexec tool via /proc interface.
One such attrubute is 'chosen/linux,memory_limit' that is used to pass
memory limit of the running kernel.
This was initialized using kernel's 'memory_limit' variable, that is set
by early init code based on mem= kernel parameter and other reasons.
But there are cases when memory_limit variable does not contain proper
information. One such case is when !CONFIG_HIGHMEM kernel runs on system
with memory large enough not to fit into lowmem.
This patch fixes initialization of 'chosen/linux,memory_limit' to use
values from memblock subsystem. These are adjusted at kernel memory
management init and thus always contain values that match reality.
Signed-off-by: Nikita Yushchenko <nyushchenko@dev.rtsoft.ru>
---
arch/powerpc/kernel/machine_kexec.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec.c
index 015ae55..372cda5 100644
--- a/arch/powerpc/kernel/machine_kexec.c
+++ b/arch/powerpc/kernel/machine_kexec.c
@@ -250,8 +250,14 @@ static void __init export_crashk_values(struct device_node *node)
/*
* memory_limit is required by the kexec-tools to limit the
* crash regions to the actual memory used.
+ *
+ * There are cases when memory_limit variable does not hold actual
+ * limit, for example when memory was limited by no kernel support
+ * for HIGHMEM. Reliable information is known by memblock because
+ * memory management init adjusts it.
*/
- mem_limit = cpu_to_be_ulong(memory_limit);
+ mem_limit = cpu_to_be_ulong(memblock_end_of_DRAM() -
+ memblock_start_of_DRAM());
of_update_property(node, &memory_limit_prop);
}
--
1.7.10.4
^ permalink raw reply related
* Re: [PATCH 0/3] powerpc/perf: Enable linking with libunwind
From: Jiri Olsa @ 2014-03-06 17:49 UTC (permalink / raw)
To: Sukadev Bhattiprolu
Cc: Michael Ellerman, linux-kernel, Stephane Eranian, linuxppc-dev,
Paul Mackerras, Arnaldo Carvalho de Melo, Jean Pihet
In-Reply-To: <1394080919-17957-1-git-send-email-sukadev@linux.vnet.ibm.com>
On Wed, Mar 05, 2014 at 08:41:56PM -0800, Sukadev Bhattiprolu wrote:
> When we try to create backtraces (call-graphs) with the perf tool
>
> perf record -g /tmp/sprintft
>
> we get backtraces with duplicate arcs for sprintft[1]:
>
> 14.61% sprintft libc-2.18.so [.] __random
> |
> --- __random
> |
> |--61.09%-- __random
> | |
> | |--97.18%-- rand
> | | do_my_sprintf
> | | main
> | | generic_start_main.isra.0
> | | __libc_start_main
> | | 0x0
> | |
> | --2.82%-- do_my_sprintf
> | main
> | generic_start_main.isra.0
> | __libc_start_main
> | 0x0
> |
> --38.91%-- rand
> |
> |--92.90%-- rand
> | |
> | |--99.87%-- do_my_sprintf
> | | main
> | | generic_start_main.isra.0
> | | __libc_start_main
> | | 0x0
> | --0.13%-- [...]
> |
> --7.10%-- do_my_sprintf
> main
> generic_start_main.isra.0
> __libc_start_main
> 0x0
>
> (where the two arcs both have the same backtrace but are not merged).
>
> Linking with libunwind seems to create better backtraces. While x86 and
> ARM processors have support for linking with libunwind but Power does not.
> This patchset is an RFC for linking with libunwind.
>
> With this patchset and running:
>
> /tmp/perf record --call-graph=dwarf,8192 /tmp/sprintft
>
> the backtrace is:
>
> 14.94% sprintft libc-2.18.so [.] __random
> |
> --- __random
> rand
> do_my_sprintf
> main
> generic_start_main.isra.0
> __libc_start_main
> (nil)
>
> This appears better.
>
> One downside is that we now need the kernel to save the entire user stack
> (the 8192 in the command line is the default user stack size).
>
> A second issue is that this invocation of perf (with --call-graph=dwarf,8192)
> seems to fail for backtraces involving tail-calls[2]
>
> /tmp/perf record -g ./tailcall
> gives
>
> 20.00% tailcall tailcall [.] work2
> |
> --- work2
> work
>
> shows the tail function 'work2' as "called from" 'work()'
>
> But with libunwind:
>
> /tmp/perf record --call-graph=dwarf,8192 ./tailcall
> we get:
>
> 20.50% tailcall tailcall [.] work2
> |
> --- work2
>
> the caller of 'work' is not shown.
>
> I am debugging this, but would appreciate any feedback/pointers on the
> patchset/direction:
>
> - Does libunwind need the entire user stack to work or are there
> optimizations we can do to save the minimal entries for it to
> perform the unwind.
AFAIK you dont need to provide whole stack, but the more
you have the bigger chance you'll get full(er) backtrace
>
> - Does libunwind work with tailcalls like the one above ?
not sure, but if you have x86 alternative to your tailcall (i cannot
read ppc assembly) I could try on x86 ;-)
CC-ing Jean, as he might have seen this issue..
>
> - Are there benefits to linking with libunwind (even if it does not
> yet solve the tailcall problem)
provides backtrace for binaries/distros/archs compiled without framepointer
>
> - Are there any examples of using libdwarf to solve the tailcall
> issue ?
btw there's now remote unwinder in elfutils (version 0.158)
the perf supprot is in Arnaldo's perf/core tree
jirka
^ permalink raw reply
* Re: [PATCH 3/3] perf: Use 64-bit value when comparing sample_regs
From: Jiri Olsa @ 2014-03-06 17:06 UTC (permalink / raw)
To: Gabriel Paubert
Cc: Michael Ellerman, linux-kernel@vger.kernel.org, Stephane Eranian,
linuxppc-dev@ozlabs.org, David Laight, Paul Mackerras,
Arnaldo Carvalho de Melo, 'Sukadev Bhattiprolu'
In-Reply-To: <20140306113332.GA7827@visitor2.iram.es>
On Thu, Mar 06, 2014 at 12:33:32PM +0100, Gabriel Paubert wrote:
> On Thu, Mar 06, 2014 at 09:44:47AM +0000, David Laight wrote:
> > From: Sukadev Bhattiprolu
> > > When checking whether a bit representing a register is set in
> > > sample_regs, a 64-bit mask, use 64-bit value (1LL).
> > >
> > > Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
> > > ---
> > > tools/perf/util/unwind.c | 4 ++--
> > > 1 file changed, 2 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/tools/perf/util/unwind.c b/tools/perf/util/unwind.c
> > > index 742f23b..2b888c6 100644
> > > --- a/tools/perf/util/unwind.c
> > > +++ b/tools/perf/util/unwind.c
> > > @@ -396,11 +396,11 @@ static int reg_value(unw_word_t *valp, struct regs_dump *regs, int id,
> > > {
> > > int i, idx = 0;
> > >
> > > - if (!(sample_regs & (1 << id)))
> > > + if (!(sample_regs & (1LL << id)))
> > > return -EINVAL;
> > >
> > > for (i = 0; i < id; i++) {
> > > - if (sample_regs & (1 << i))
> > > + if (sample_regs & (1LL << i))
> > > idx++;
> > > }
> >
> > There are much faster ways to count the number of set bits, especially
> > if you might need to check a significant number of bits.
> > There might even be a function defined somewhere to do it.
>
> Indeed, look for Hamming weight (hweight family of functions)
> in asm/hweight.h and what is included from there.
>
> Besides that, many modern processors also have a machine instruction
> to perform this task. In the processor manuals the instruction is
> described as population count and the mnemonic starts with "popcnt"
> on x86 and ppc.
>
> Gabriel
>
> > Basically you just add up the bits, for 16 bit it would be:
> > val = (val & 0x5555) + (val >> 1) & 0x5555;
> > val = (val & 0x3333) + (val >> 2) & 0x3333;
> > val = (val & 0x0f0f) + (val >> 4) & 0x0f0f;
> > val = (val & 0x00ff) + (val >> 8) & 0x00ff;
> > As the size of the work increases the improvement is more significant.
> > (Some of the later masking can probably be proven unnecessary.)
right I think the loop could be replaced by:
idx = hweight(mask & ((1 << id) - 1))
Sukadev,
please also rebase against latest Arnaldo's perf/core,
this code has changed just recently, it's now in:
util/perf_regs.c:perf_reg_value
thanks,
jirka
^ permalink raw reply
* Re: ibmveth: Fix endian issues with MAC addresses
From: David Miller @ 2014-03-06 21:27 UTC (permalink / raw)
To: anton; +Cc: linuxppc-dev, dvaleev, agraf, netdev, joe, santil
In-Reply-To: <20140305145137.3460dbe7@kryten>
From: Anton Blanchard <anton@samba.org>
Date: Wed, 5 Mar 2014 14:51:37 +1100
> The code to load a MAC address into a u64 for passing to the
> hypervisor via a register is broken on little endian.
>
> Create a helper function called ibmveth_encode_mac_addr
> which does the right thing in both big and little endian.
>
> We were storing the MAC address in a long in struct ibmveth_adapter.
> It's never used so remove it - we don't need another place in the
> driver where we create endian issues with MAC addresses.
>
> Signed-off-by: Anton Blanchard <anton@samba.org>
> Cc: stable@vger.kernel.org
Applied, thanks Anton.
> - memcpy(&adapter->mac_addr, mac_addr_p, ETH_ALEN);
...
> - unsigned long mac_addr;
That's some scary stuff right there.
^ permalink raw reply
* Re: [PATCH] kexec/powerpc: fix exporting memory limit
From: Michael Ellerman @ 2014-03-07 0:47 UTC (permalink / raw)
To: Nikita Yushchenko
Cc: yadviga, lugovskoy, kexec, linux-kernel, Paul Mackerras,
Anton Blanchard, Mahesh Salgaonkar, Hari Bathini, linuxppc-dev
In-Reply-To: <1394115854-11709-1-git-send-email-nyushchenko@dev.rtsoft.ru>
On Thu, 2014-03-06 at 18:24 +0400, Nikita Yushchenko wrote:
> When preparing dump-capturing kernel, kexec userspace tool needs to know
> actual amount of memory used by the running kernel. This may differ from
> extire available DRAM for a couple of reasons. To address this issue,
> kdump kernel support code injects several attributes into device tree that
> are later captured by userspace kexec tool via /proc interface.
>
> One such attrubute is 'chosen/linux,memory_limit' that is used to pass
> memory limit of the running kernel.
>
> This was initialized using kernel's 'memory_limit' variable, that is set
> by early init code based on mem= kernel parameter and other reasons.
>
> But there are cases when memory_limit variable does not contain proper
> information. One such case is when !CONFIG_HIGHMEM kernel runs on system
> with memory large enough not to fit into lowmem.
Why doesn't the !CONFIG_HIGHMEM code update memory_limit to reflect reality.
cheers
^ permalink raw reply
* Re: [PATCH v2 14/52] powerpc, sysfs: Fix CPU hotplug callback registration
From: Benjamin Herrenschmidt @ 2014-03-07 2:57 UTC (permalink / raw)
To: Srivatsa S. Bhat
Cc: linux-arch, ego, walken, linux, akpm, Wang Dongsheng, peterz,
rusty, rjw, oleg, linux-kernel, Olof Johansson,
Madhavan Srinivasan, paulus, tj, tglx, paulmck, linuxppc-dev,
mingo
In-Reply-To: <20140214075215.22701.23653.stgit@srivatsabhat.in.ibm.com>
On Fri, 2014-02-14 at 13:22 +0530, Srivatsa S. Bhat wrote:
> Subsystems that want to register CPU hotplug callbacks, as well as perform
> initialization for the CPUs that are already online, often do it as shown
> below:
>
> get_online_cpus();
>
> for_each_online_cpu(cpu)
> init_cpu(cpu);
>
> register_cpu_notifier(&foobar_cpu_notifier);
>
> put_online_cpus();
This patch breaks a good half of my test configs with:
/home/benh/linux-powerpc-test/arch/powerpc/kernel/sysfs.c: In function 'topology_init':
/home/benh/linux-powerpc-test/arch/powerpc/kernel/sysfs.c:979:2: error: implicit declaration of function 'cpu_notifier_register_begin' [-Werror=implicit-function-declaration]
/home/benh/linux-powerpc-test/arch/powerpc/kernel/sysfs.c:1004:2: error: implicit declaration of function '__register_cpu_notifier' [-Werror=implicit-function-declaration]
/home/benh/linux-powerpc-test/arch/powerpc/kernel/sysfs.c:1006:2: error: implicit declaration of function 'cpu_notifier_register_done' [-Werror=implicit-function-declaration]
cc1: all warnings being treated as errors
make[2]: *** [arch/powerpc/kernel/sysfs.o] Error 1
make[2]: *** Waiting for unfinished jobs....
^ permalink raw reply
* Re: [PATCH RFC/RFT v3 6/9] powerpc: move cacheinfo sysfs to generic cacheinfo infrastructure
From: Anshuman Khandual @ 2014-03-07 4:06 UTC (permalink / raw)
To: Sudeep Holla; +Cc: linuxppc-dev, Paul Mackerras, linux-kernel
In-Reply-To: <1392825976-17633-7-git-send-email-sudeep.holla@arm.com>
On 02/19/2014 09:36 PM, Sudeep Holla wrote:
> From: Sudeep Holla <sudeep.holla@arm.com>
>
> This patch removes the redundant sysfs cacheinfo code by making use of
> the newly introduced generic cacheinfo infrastructure.
>
> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Cc: Paul Mackerras <paulus@samba.org>
> Cc: linuxppc-dev@lists.ozlabs.org
> ---
> arch/powerpc/kernel/cacheinfo.c | 831 ++++++----------------------------------
> arch/powerpc/kernel/cacheinfo.h | 8 -
> arch/powerpc/kernel/sysfs.c | 4 -
> 3 files changed, 109 insertions(+), 734 deletions(-)
> delete mode 100644 arch/powerpc/kernel/cacheinfo.h
>
> diff --git a/arch/powerpc/kernel/cacheinfo.c b/arch/powerpc/kernel/cacheinfo.c
> index 2912b87..05b7580 100644
> --- a/arch/powerpc/kernel/cacheinfo.c
> +++ b/arch/powerpc/kernel/cacheinfo.c
> @@ -10,38 +10,10 @@
> * 2 as published by the Free Software Foundation.
> */
>
> +#include <linux/cacheinfo.h>
> #include <linux/cpu.h>
> -#include <linux/cpumask.h>
> #include <linux/kernel.h>
> -#include <linux/kobject.h>
> -#include <linux/list.h>
> -#include <linux/notifier.h>
> #include <linux/of.h>
> -#include <linux/percpu.h>
> -#include <linux/slab.h>
> -#include <asm/prom.h>
> -
> -#include "cacheinfo.h"
> -
> -/* per-cpu object for tracking:
> - * - a "cache" kobject for the top-level directory
> - * - a list of "index" objects representing the cpu's local cache hierarchy
> - */
> -struct cache_dir {
> - struct kobject *kobj; /* bare (not embedded) kobject for cache
> - * directory */
> - struct cache_index_dir *index; /* list of index objects */
> -};
> -
> -/* "index" object: each cpu's cache directory has an index
> - * subdirectory corresponding to a cache object associated with the
> - * cpu. This object's lifetime is managed via the embedded kobject.
> - */
> -struct cache_index_dir {
> - struct kobject kobj;
> - struct cache_index_dir *next; /* next index in parent directory */
> - struct cache *cache;
> -};
>
> /* Template for determining which OF properties to query for a given
> * cache type */
> @@ -60,11 +32,6 @@ struct cache_type_info {
> const char *nr_sets_prop;
> };
>
> -/* These are used to index the cache_type_info array. */
> -#define CACHE_TYPE_UNIFIED 0
> -#define CACHE_TYPE_INSTRUCTION 1
> -#define CACHE_TYPE_DATA 2
> -
> static const struct cache_type_info cache_type_info[] = {
> {
> /* PowerPC Processor binding says the [di]-cache-*
> @@ -77,246 +44,115 @@ static const struct cache_type_info cache_type_info[] = {
> .nr_sets_prop = "d-cache-sets",
> },
> {
> - .name = "Instruction",
> - .size_prop = "i-cache-size",
> - .line_size_props = { "i-cache-line-size",
> - "i-cache-block-size", },
> - .nr_sets_prop = "i-cache-sets",
> - },
> - {
> .name = "Data",
> .size_prop = "d-cache-size",
> .line_size_props = { "d-cache-line-size",
> "d-cache-block-size", },
> .nr_sets_prop = "d-cache-sets",
> },
> + {
> + .name = "Instruction",
> + .size_prop = "i-cache-size",
> + .line_size_props = { "i-cache-line-size",
> + "i-cache-block-size", },
> + .nr_sets_prop = "i-cache-sets",
> + },
> };
Hey Sudeep,
After applying this patch, the cache_type_info array looks like this.
static const struct cache_type_info cache_type_info[] = {
{
/*
* PowerPC Processor binding says the [di]-cache-*
* must be equal on unified caches, so just use
* d-cache properties.
*/
.name = "Unified",
.size_prop = "d-cache-size",
.line_size_props = { "d-cache-line-size",
"d-cache-block-size", },
.nr_sets_prop = "d-cache-sets",
},
{
.name = "Data",
.size_prop = "d-cache-size",
.line_size_props = { "d-cache-line-size",
"d-cache-block-size", },
.nr_sets_prop = "d-cache-sets",
},
{
.name = "Instruction",
.size_prop = "i-cache-size",
.line_size_props = { "i-cache-line-size",
"i-cache-block-size", },
.nr_sets_prop = "i-cache-sets",
},
};
and this function computes the the array index for any given cache type
define for PowerPC.
static inline int get_cacheinfo_idx(enum cache_type type)
{
if (type == CACHE_TYPE_UNIFIED)
return 0;
else
return type;
}
These types are define in include/linux/cacheinfo.h as
enum cache_type {
CACHE_TYPE_NOCACHE = 0,
CACHE_TYPE_INST = BIT(0), ---> 1
CACHE_TYPE_DATA = BIT(1), ---> 2
CACHE_TYPE_SEPARATE = CACHE_TYPE_INST | CACHE_TYPE_DATA,
CACHE_TYPE_UNIFIED = BIT(2),
};
When it is UNIFIED we return index 0, which is correct. But the index
for instruction and data cache seems to be swapped which wrong. This
will fetch invalid properties for any given cache type.
I have done some initial review and testing for this patch's impact on
PowerPC (ppc64 POWER specifically). I am trying to do some code clean-up
and re-arrangements. Will post out soon. Thanks !
Regards
Anshuman
^ permalink raw reply
* [PATCH 1/9] powerpc/fsl: add PVR definition for E500MC and E5500
From: Chenhui Zhao @ 2014-03-07 4:57 UTC (permalink / raw)
To: linuxppc-dev; +Cc: scottwood, linux-kernel, Jason.Jin
From: Wang Dongsheng <dongsheng.wang@freescale.com>
Signed-off-by: Wang Dongsheng <dongsheng.wang@freescale.com>
---
arch/powerpc/include/asm/reg.h | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 62b114e..cd7b630 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -1075,6 +1075,8 @@
#define PVR_8560 0x80200000
#define PVR_VER_E500V1 0x8020
#define PVR_VER_E500V2 0x8021
+#define PVR_VER_E500MC 0x8023
+#define PVR_VER_E5500 0x8024
#define PVR_VER_E6500 0x8040
/*
--
1.7.3
^ permalink raw reply related
* [PATCH 2/9] powerpc/cache: add cache flush operation for various e500
From: Chenhui Zhao @ 2014-03-07 4:57 UTC (permalink / raw)
To: linuxppc-dev; +Cc: scottwood, linux-kernel, Jason.Jin
In-Reply-To: <1394168285-32275-1-git-send-email-chenhui.zhao@freescale.com>
Various e500 core have different cache architecture, so they
need different cache flush operations. Therefore, add a callback
function cpu_flush_caches to the struct cpu_spec. The cache flush
operation for the specific kind of e500 is selected at init time.
The callback function will flush all caches in the current cpu.
Signed-off-by: Chenhui Zhao <chenhui.zhao@freescale.com>
---
arch/powerpc/include/asm/cacheflush.h | 2 -
arch/powerpc/include/asm/cputable.h | 11 +++
arch/powerpc/kernel/asm-offsets.c | 3 +
arch/powerpc/kernel/cpu_setup_fsl_booke.S | 114 ++++++++++++++++++++++++++++-
arch/powerpc/kernel/cputable.c | 4 +
arch/powerpc/kernel/head_fsl_booke.S | 74 -------------------
arch/powerpc/platforms/85xx/smp.c | 4 +-
7 files changed, 134 insertions(+), 78 deletions(-)
diff --git a/arch/powerpc/include/asm/cacheflush.h b/arch/powerpc/include/asm/cacheflush.h
index 5b93122..039753e 100644
--- a/arch/powerpc/include/asm/cacheflush.h
+++ b/arch/powerpc/include/asm/cacheflush.h
@@ -30,8 +30,6 @@ extern void flush_dcache_page(struct page *page);
#define flush_dcache_mmap_lock(mapping) do { } while (0)
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
-extern void __flush_disable_L1(void);
-
extern void flush_icache_range(unsigned long, unsigned long);
extern void flush_icache_user_range(struct vm_area_struct *vma,
struct page *page, unsigned long addr,
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
index 617cc76..2c497a2 100644
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -43,6 +43,13 @@ extern int machine_check_e500(struct pt_regs *regs);
extern int machine_check_e200(struct pt_regs *regs);
extern int machine_check_47x(struct pt_regs *regs);
+#if defined(CONFIG_E500) || defined(CONFIG_PPC_E500MC)
+extern void __flush_caches_e500v2(void);
+extern void __flush_caches_e500mc(void);
+extern void __flush_caches_e5500(void);
+extern void __flush_caches_e6500(void);
+#endif
+
/* NOTE WELL: Update identify_cpu() if fields are added or removed! */
struct cpu_spec {
/* CPU is matched via (PVR & pvr_mask) == pvr_value */
@@ -59,6 +66,10 @@ struct cpu_spec {
unsigned int icache_bsize;
unsigned int dcache_bsize;
+#if defined(CONFIG_E500) || defined(CONFIG_PPC_E500MC)
+ /* flush caches of the cpu which is running the function */
+ void (*cpu_flush_caches)(void);
+#endif
/* number of performance monitor counters */
unsigned int num_pmcs;
enum powerpc_pmc_type pmc_type;
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 8d1d94d..5157fb4 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -372,6 +372,9 @@ int main(void)
DEFINE(CPU_SPEC_FEATURES, offsetof(struct cpu_spec, cpu_features));
DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup));
DEFINE(CPU_SPEC_RESTORE, offsetof(struct cpu_spec, cpu_restore));
+#if defined(CONFIG_E500) || defined(CONFIG_PPC_E500MC)
+ DEFINE(CPU_FLUSH_CACHES, offsetof(struct cpu_spec, cpu_flush_caches));
+#endif
DEFINE(pbe_address, offsetof(struct pbe, address));
DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address));
diff --git a/arch/powerpc/kernel/cpu_setup_fsl_booke.S b/arch/powerpc/kernel/cpu_setup_fsl_booke.S
index cc2d896..e59d6de 100644
--- a/arch/powerpc/kernel/cpu_setup_fsl_booke.S
+++ b/arch/powerpc/kernel/cpu_setup_fsl_booke.S
@@ -1,7 +1,7 @@
/*
* This file contains low level CPU setup functions.
* Kumar Gala <galak@kernel.crashing.org>
- * Copyright 2009 Freescale Semiconductor, Inc.
+ * Copyright 2009, 2014 Freescale Semiconductor, Inc.
*
* Based on cpu_setup_6xx code by
* Benjamin Herrenschmidt <benh@kernel.crashing.org>
@@ -13,11 +13,13 @@
*
*/
+#include <asm/page.h>
#include <asm/processor.h>
#include <asm/cputable.h>
#include <asm/ppc_asm.h>
#include <asm/mmu-book3e.h>
#include <asm/asm-offsets.h>
+#include <asm/mpc85xx.h>
_GLOBAL(__e500_icache_setup)
mfspr r0, SPRN_L1CSR1
@@ -223,3 +225,113 @@ _GLOBAL(__setup_cpu_e5500)
mtlr r5
blr
#endif
+
+/* flush L1 date cache, it can apply to e500v2, e500mc and e5500 */
+_GLOBAL(flush_dcache_L1)
+ mfmsr r10
+ wrteei 0
+
+ mfspr r3,SPRN_L1CFG0
+ rlwinm r5,r3,9,3 /* Extract cache block size */
+ twlgti r5,1 /* Only 32 and 64 byte cache blocks
+ * are currently defined.
+ */
+ li r4,32
+ subfic r6,r5,2 /* r6 = log2(1KiB / cache block size) -
+ * log2(number of ways)
+ */
+ slw r5,r4,r5 /* r5 = cache block size */
+
+ rlwinm r7,r3,0,0xff /* Extract number of KiB in the cache */
+ mulli r7,r7,13 /* An 8-way cache will require 13
+ * loads per set.
+ */
+ slw r7,r7,r6
+
+ /* save off HID0 and set DCFA */
+ mfspr r8,SPRN_HID0
+ ori r9,r8,HID0_DCFA@l
+ mtspr SPRN_HID0,r9
+ isync
+
+ LOAD_REG_IMMEDIATE(r6, KERNELBASE)
+ mr r4, r6
+ mtctr r7
+
+1: lwz r3,0(r4) /* Load... */
+ add r4,r4,r5
+ bdnz 1b
+
+ msync
+ mr r4, r6
+ mtctr r7
+
+1: dcbf 0,r4 /* ...and flush. */
+ add r4,r4,r5
+ bdnz 1b
+
+ /* restore HID0 */
+ mtspr SPRN_HID0,r8
+ isync
+
+ wrtee r10
+
+ blr
+
+has_L2_cache:
+ /* skip L2 cache on P2040/P2040E as they have no L2 cache */
+ mfspr r3, SPRN_SVR
+ /* shift right by 8 bits and clear E bit of SVR */
+ rlwinm r4, r3, 24, ~0x800
+
+ lis r3, SVR_P2040@h
+ ori r3, r3, SVR_P2040@l
+ cmpw r4, r3
+ beq 1f
+
+ li r3, 1
+ blr
+1:
+ li r3, 0
+ blr
+
+/* flush backside L2 cache */
+flush_backside_L2_cache:
+ mflr r10
+ bl has_L2_cache
+ mtlr r10
+ cmpwi r3, 0
+ beq 2f
+
+ /* Flush the L2 cache */
+ mfspr r3, SPRN_L2CSR0
+ ori r3, r3, L2CSR0_L2FL@l
+ msync
+ isync
+ mtspr SPRN_L2CSR0,r3
+ isync
+
+ /* check if it is complete */
+1: mfspr r3,SPRN_L2CSR0
+ andi. r3, r3, L2CSR0_L2FL@l
+ bne 1b
+2:
+ blr
+
+_GLOBAL(__flush_caches_e500v2)
+ mflr r0
+ bl flush_dcache_L1
+ mtlr r0
+ blr
+
+_GLOBAL(__flush_caches_e500mc)
+_GLOBAL(__flush_caches_e5500)
+ mflr r0
+ bl flush_dcache_L1
+ bl flush_backside_L2_cache
+ mtlr r0
+ blr
+
+/* L1 Data Cache of e6500 contains no modified data, no flush is required */
+_GLOBAL(__flush_caches_e6500)
+ blr
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 6c8dd5d..8e70aa7 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -2068,6 +2068,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.cpu_setup = __setup_cpu_e500v2,
.machine_check = machine_check_e500,
.platform = "ppc8548",
+ .cpu_flush_caches = __flush_caches_e500v2,
},
{ /* e500mc */
.pvr_mask = 0xffff0000,
@@ -2086,6 +2087,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.cpu_setup = __setup_cpu_e500mc,
.machine_check = machine_check_e500mc,
.platform = "ppce500mc",
+ .cpu_flush_caches = __flush_caches_e500mc,
},
#endif /* CONFIG_PPC32 */
{ /* e5500 */
@@ -2108,6 +2110,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
#endif
.machine_check = machine_check_e500mc,
.platform = "ppce5500",
+ .cpu_flush_caches = __flush_caches_e5500,
},
{ /* e6500 */
.pvr_mask = 0xffff0000,
@@ -2130,6 +2133,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
#endif
.machine_check = machine_check_e500mc,
.platform = "ppce6500",
+ .cpu_flush_caches = __flush_caches_e6500,
},
#ifdef CONFIG_PPC32
{ /* default match */
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index b497188..20204fe 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -1067,80 +1067,6 @@ _GLOBAL(set_context)
isync /* Force context change */
blr
-_GLOBAL(flush_dcache_L1)
- mfspr r3,SPRN_L1CFG0
-
- rlwinm r5,r3,9,3 /* Extract cache block size */
- twlgti r5,1 /* Only 32 and 64 byte cache blocks
- * are currently defined.
- */
- li r4,32
- subfic r6,r5,2 /* r6 = log2(1KiB / cache block size) -
- * log2(number of ways)
- */
- slw r5,r4,r5 /* r5 = cache block size */
-
- rlwinm r7,r3,0,0xff /* Extract number of KiB in the cache */
- mulli r7,r7,13 /* An 8-way cache will require 13
- * loads per set.
- */
- slw r7,r7,r6
-
- /* save off HID0 and set DCFA */
- mfspr r8,SPRN_HID0
- ori r9,r8,HID0_DCFA@l
- mtspr SPRN_HID0,r9
- isync
-
- lis r4,KERNELBASE@h
- mtctr r7
-
-1: lwz r3,0(r4) /* Load... */
- add r4,r4,r5
- bdnz 1b
-
- msync
- lis r4,KERNELBASE@h
- mtctr r7
-
-1: dcbf 0,r4 /* ...and flush. */
- add r4,r4,r5
- bdnz 1b
-
- /* restore HID0 */
- mtspr SPRN_HID0,r8
- isync
-
- blr
-
-/* Flush L1 d-cache, invalidate and disable d-cache and i-cache */
-_GLOBAL(__flush_disable_L1)
- mflr r10
- bl flush_dcache_L1 /* Flush L1 d-cache */
- mtlr r10
-
- mfspr r4, SPRN_L1CSR0 /* Invalidate and disable d-cache */
- li r5, 2
- rlwimi r4, r5, 0, 3
-
- msync
- isync
- mtspr SPRN_L1CSR0, r4
- isync
-
-1: mfspr r4, SPRN_L1CSR0 /* Wait for the invalidate to finish */
- andi. r4, r4, 2
- bne 1b
-
- mfspr r4, SPRN_L1CSR1 /* Invalidate and disable i-cache */
- li r5, 2
- rlwimi r4, r5, 0, 3
-
- mtspr SPRN_L1CSR1, r4
- isync
-
- blr
-
#ifdef CONFIG_SMP
/* When we get here, r24 needs to hold the CPU # */
.globl __secondary_start
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index 6382098..2e5911e 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -137,7 +137,9 @@ static void smp_85xx_mach_cpu_die(void)
mtspr(SPRN_TCR, 0);
- __flush_disable_L1();
+ if (cur_cpu_spec && cur_cpu_spec->cpu_flush_caches)
+ cur_cpu_spec->cpu_flush_caches();
+
tmp = (mfspr(SPRN_HID0) & ~(HID0_DOZE|HID0_SLEEP)) | HID0_NAP;
mtspr(SPRN_HID0, tmp);
isync();
--
1.7.3
^ permalink raw reply related
* [PATCH 4/9] powerpc/85xx: support CPU hotplug for e500mc and e5500
From: Chenhui Zhao @ 2014-03-07 4:58 UTC (permalink / raw)
To: linuxppc-dev; +Cc: scottwood, linux-kernel, Jason.Jin
In-Reply-To: <1394168285-32275-1-git-send-email-chenhui.zhao@freescale.com>
Implemented CPU hotplug on e500mc and e5500. On e5500 both 32-bit and
64-bit modes can work. Used some callback functions implemented in RCPM
driver.
Signed-off-by: Chenhui Zhao <chenhui.zhao@freescale.com>
---
arch/powerpc/Kconfig | 2 +-
arch/powerpc/kernel/smp.c | 6 ++-
arch/powerpc/mm/tlb_nohash.c | 6 ++-
arch/powerpc/platforms/85xx/smp.c | 94 ++++++++++++++++++++++++++++++-------
4 files changed, 87 insertions(+), 21 deletions(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index a5e5d2e..05f6323 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -362,7 +362,7 @@ config SWIOTLB
config HOTPLUG_CPU
bool "Support for enabling/disabling CPUs"
depends on SMP && (PPC_PSERIES || \
- PPC_PMAC || PPC_POWERNV || (PPC_85xx && !PPC_E500MC))
+ PPC_PMAC || PPC_POWERNV || FSL_SOC_BOOKE)
---help---
Say Y here to be able to disable and re-enable individual
CPUs at runtime on SMP machines.
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index ac2621a..f3f4401 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -405,8 +405,12 @@ void generic_cpu_die(unsigned int cpu)
for (i = 0; i < 100; i++) {
smp_rmb();
- if (per_cpu(cpu_state, cpu) == CPU_DEAD)
+ if (per_cpu(cpu_state, cpu) == CPU_DEAD) {
+#ifdef CONFIG_PPC64
+ paca[cpu].cpu_start = 0;
+#endif
return;
+ }
msleep(100);
}
printk(KERN_ERR "CPU%d didn't die...\n", cpu);
diff --git a/arch/powerpc/mm/tlb_nohash.c b/arch/powerpc/mm/tlb_nohash.c
index b37a58e..d24e06c 100644
--- a/arch/powerpc/mm/tlb_nohash.c
+++ b/arch/powerpc/mm/tlb_nohash.c
@@ -648,8 +648,10 @@ static void __early_init_mmu(int boot_cpu)
num_cams = (mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY) / 4;
linear_map_top = map_mem_in_cams(linear_map_top, num_cams);
- /* limit memory so we dont have linear faults */
- memblock_enforce_memory_limit(linear_map_top);
+ if (boot_cpu) {
+ /* limit memory so we dont have linear faults */
+ memblock_enforce_memory_limit(linear_map_top);
+ }
if (book3e_htw_mode == PPC_HTW_NONE) {
patch_exception(0x1c0, exc_data_tlb_miss_bolted_book3e);
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index 2e5911e..0047883 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -19,6 +19,7 @@
#include <linux/kexec.h>
#include <linux/highmem.h>
#include <linux/cpu.h>
+#include <linux/smp.h>
#include <asm/machdep.h>
#include <asm/pgtable.h>
@@ -46,6 +47,17 @@ static u64 timebase;
static int tb_req;
static int tb_valid;
+#ifdef CONFIG_PPC_E500MC
+/* specify the cpu PM state when cpu dies, PH15/NAP is the default */
+int qoriq_cpu_die_state = E500_PM_PH15;
+#endif
+
+#ifdef CONFIG_PPC_E500MC
+static void mpc85xx_timebase_freeze(int freeze)
+{
+ qoriq_pm_ops->freeze_time_base(freeze);
+}
+#else
static void mpc85xx_timebase_freeze(int freeze)
{
uint32_t mask;
@@ -58,6 +70,7 @@ static void mpc85xx_timebase_freeze(int freeze)
in_be32(&guts->devdisr);
}
+#endif
static void mpc85xx_give_timebase(void)
{
@@ -125,6 +138,34 @@ static void mpc85xx_take_timebase(void)
}
#ifdef CONFIG_HOTPLUG_CPU
+#ifdef CONFIG_PPC_E500MC
+static void qoriq_cpu_die(void)
+{
+ unsigned int cpu = smp_processor_id();
+
+ local_irq_disable();
+#ifdef CONFIG_PPC64
+ __hard_irq_disable();
+#endif
+ idle_task_exit();
+
+ if (qoriq_pm_ops->irq_mask)
+ qoriq_pm_ops->irq_mask(cpu);
+
+ mtspr(SPRN_TCR, 0);
+ mtspr(SPRN_TSR, mfspr(SPRN_TSR));
+
+ generic_set_cpu_dead(cpu);
+
+ if (cur_cpu_spec && cur_cpu_spec->cpu_flush_caches)
+ cur_cpu_spec->cpu_flush_caches();
+
+ qoriq_pm_ops->cpu_enter_state(cpu, qoriq_cpu_die_state);
+
+ while (1)
+ ;
+}
+#else
static void smp_85xx_mach_cpu_die(void)
{
unsigned int cpu = smp_processor_id();
@@ -155,6 +196,7 @@ static void smp_85xx_mach_cpu_die(void)
;
}
#endif
+#endif
static inline void flush_spin_table(void *spin_table)
{
@@ -208,11 +250,8 @@ static int smp_85xx_kick_cpu(int nr)
spin_table = phys_to_virt(*cpu_rel_addr);
local_irq_save(flags);
-#ifdef CONFIG_PPC32
-#ifdef CONFIG_HOTPLUG_CPU
- /* Corresponding to generic_set_cpu_dead() */
- generic_set_cpu_up(nr);
+#ifdef CONFIG_HOTPLUG_CPU
if (system_state == SYSTEM_RUNNING) {
/*
* To keep it compatible with old boot program which uses
@@ -225,6 +264,12 @@ static int smp_85xx_kick_cpu(int nr)
out_be32(&spin_table->addr_l, 0);
flush_spin_table(spin_table);
+#ifdef CONFIG_PPC_E500MC
+ /* Due to an erratum, wake the core before reset. */
+ if (qoriq_pm_ops && qoriq_pm_ops->cpu_exit_state)
+ qoriq_pm_ops->cpu_exit_state(nr, qoriq_cpu_die_state);
+#endif
+
/*
* We don't set the BPTR register here since it already points
* to the boot page properly.
@@ -247,13 +292,30 @@ static int smp_85xx_kick_cpu(int nr)
/* clear the acknowledge status */
__secondary_hold_acknowledge = -1;
+
+#ifdef CONFIG_PPC_E500MC
+ if (qoriq_pm_ops->irq_unmask)
+ qoriq_pm_ops->irq_unmask(nr);
+#endif
}
+
+ /* Corresponding to generic_set_cpu_dead() */
+ generic_set_cpu_up(nr);
#endif
+
flush_spin_table(spin_table);
out_be32(&spin_table->pir, hw_cpu);
+#ifdef CONFIG_PPC32
out_be32(&spin_table->addr_l, __pa(__early_start));
+#else
+ out_be32(&spin_table->addr_h,
+ __pa(*(u64 *)generic_secondary_smp_init) >> 32);
+ out_be32(&spin_table->addr_l,
+ __pa(*(u64 *)generic_secondary_smp_init) & 0xffffffff);
+#endif
flush_spin_table(spin_table);
+#ifdef CONFIG_PPC32
/* Wait a bit for the CPU to ack. */
if (!spin_event_timeout(__secondary_hold_acknowledge == hw_cpu,
10000, 100)) {
@@ -262,17 +324,10 @@ static int smp_85xx_kick_cpu(int nr)
ret = -ENOENT;
goto out;
}
-out:
#else
smp_generic_kick_cpu(nr);
-
- flush_spin_table(spin_table);
- out_be32(&spin_table->pir, hw_cpu);
- out_be64((u64 *)(&spin_table->addr_h),
- __pa((u64)*((unsigned long long *)generic_secondary_smp_init)));
- flush_spin_table(spin_table);
#endif
-
+out:
local_irq_restore(flags);
if (ioremappable)
@@ -445,13 +500,18 @@ void __init mpc85xx_smp_init(void)
__func__);
return;
}
- smp_85xx_ops.give_timebase = mpc85xx_give_timebase;
- smp_85xx_ops.take_timebase = mpc85xx_take_timebase;
-#ifdef CONFIG_HOTPLUG_CPU
- ppc_md.cpu_die = smp_85xx_mach_cpu_die;
-#endif
}
+ smp_85xx_ops.give_timebase = mpc85xx_give_timebase;
+ smp_85xx_ops.take_timebase = mpc85xx_take_timebase;
+
+#ifdef CONFIG_HOTPLUG_CPU
+#ifdef CONFIG_PPC_E500MC
+ ppc_md.cpu_die = qoriq_cpu_die;
+#else
+ ppc_md.cpu_die = smp_85xx_mach_cpu_die;
+#endif
+#endif
smp_ops = &smp_85xx_ops;
#ifdef CONFIG_KEXEC
--
1.7.3
^ permalink raw reply related
* [PATCH 5/9] powerpc/85xx: disable irq by hardware when suspend for 64-bit
From: Chenhui Zhao @ 2014-03-07 4:58 UTC (permalink / raw)
To: linuxppc-dev; +Cc: scottwood, linux-kernel, Jason.Jin
In-Reply-To: <1394168285-32275-1-git-send-email-chenhui.zhao@freescale.com>
In 64-bit mode, kernel just clears the irq soft-enable flag
in struct paca_struct to disable external irqs. But, in
the case of suspend, irqs should be disabled by hardware.
Therefore, hook a function to ppc_md.suspend_disable_irqs
to really disable irqs.
Signed-off-by: Chenhui Zhao <chenhui.zhao@freescale.com>
---
arch/powerpc/platforms/85xx/corenet_generic.c | 12 ++++++++++++
1 files changed, 12 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/platforms/85xx/corenet_generic.c b/arch/powerpc/platforms/85xx/corenet_generic.c
index 3fdf9f3..983d81f 100644
--- a/arch/powerpc/platforms/85xx/corenet_generic.c
+++ b/arch/powerpc/platforms/85xx/corenet_generic.c
@@ -32,6 +32,13 @@
#include <sysdev/fsl_pci.h>
#include "smp.h"
+#if defined(CONFIG_PPC64) && defined(CONFIG_SUSPEND)
+static void fsl_suspend_disable_irqs(void)
+{
+ __hard_irq_disable();
+}
+#endif
+
void __init corenet_gen_pic_init(void)
{
struct mpic *mpic;
@@ -58,6 +65,11 @@ void __init corenet_gen_setup_arch(void)
fsl_rcpm_init();
+#if defined(CONFIG_PPC64) && defined(CONFIG_SUSPEND)
+ /* physically disable irq for 64-bit mode when suspend */
+ ppc_md.suspend_disable_irqs = fsl_suspend_disable_irqs;
+#endif
+
pr_info("%s board from Freescale Semiconductor\n", ppc_md.name);
}
--
1.7.3
^ permalink raw reply related
* [PATCH 3/9] powerpc/rcpm: add RCPM driver
From: Chenhui Zhao @ 2014-03-07 4:57 UTC (permalink / raw)
To: linuxppc-dev; +Cc: scottwood, linux-kernel, Jason.Jin
In-Reply-To: <1394168285-32275-1-git-send-email-chenhui.zhao@freescale.com>
There is a RCPM (Run Control/Power Management) in Freescale QorIQ
series processors. The device performs tasks associated with device
run control and power management.
The driver implements some features: mask/unmask irq, enter/exit low
power states, freeze time base, etc.
There are two versions of register map in RCPM, which is specified by
the compatible entry in the RCPM node of device tree.
Signed-off-by: Chenhui Zhao <chenhui.zhao@freescale.com>
---
arch/powerpc/include/asm/fsl_guts.h | 105 ++++++++
arch/powerpc/platforms/85xx/Kconfig | 1 +
arch/powerpc/platforms/85xx/corenet_generic.c | 2 +
arch/powerpc/sysdev/Kconfig | 5 +
arch/powerpc/sysdev/Makefile | 1 +
arch/powerpc/sysdev/fsl_rcpm.c | 315 +++++++++++++++++++++++++
arch/powerpc/sysdev/fsl_soc.h | 24 ++
7 files changed, 453 insertions(+), 0 deletions(-)
create mode 100644 arch/powerpc/sysdev/fsl_rcpm.c
diff --git a/arch/powerpc/include/asm/fsl_guts.h b/arch/powerpc/include/asm/fsl_guts.h
index 77ced0b..492534a 100644
--- a/arch/powerpc/include/asm/fsl_guts.h
+++ b/arch/powerpc/include/asm/fsl_guts.h
@@ -185,5 +185,110 @@ static inline void guts_set_pmuxcr_dma(struct ccsr_guts __iomem *guts,
#endif
+struct ccsr_rcpm_v1 {
+ u8 res0000[4];
+ __be32 cdozsr; /* 0x0004 Core Doze Status Register */
+ u8 res0008[4];
+ __be32 cdozcr; /* 0x000c Core Doze Control Register */
+ u8 res0010[4];
+ __be32 cnapsr; /* 0x0014 Core Nap Status Register */
+ u8 res0018[4];
+ __be32 cnapcr; /* 0x001c Core Nap Control Register */
+ u8 res0020[4];
+ __be32 cdozpsr; /* 0x0024 Core Doze Previous Status Register */
+ u8 res0028[4];
+ __be32 cnappsr; /* 0x002c Core Nap Previous Status Register */
+ u8 res0030[4];
+ __be32 cwaitsr; /* 0x0034 Core Wait Status Register */
+ u8 res0038[4];
+ __be32 cwdtdsr; /* 0x003c Core Watchdog Detect Status Register */
+ __be32 powmgtcsr; /* 0x0040 Power Mangement Control&Status Register */
+#define RCPM_POWMGTCSR_SLP 0x00020000
+ u8 res0044[12];
+ __be32 ippdexpcr; /* 0x0050 IP Powerdown Exception Control Register */
+ u8 res0054[16];
+ __be32 cpmimr; /* 0x0064 Core PM IRQ Mask Register */
+ u8 res0068[4];
+ __be32 cpmcimr; /* 0x006c Core PM Critical IRQ Mask Register */
+ u8 res0070[4];
+ __be32 cpmmcmr; /* 0x0074 Core PM Machine Check Mask Register */
+ u8 res0078[4];
+ __be32 cpmnmimr; /* 0x007c Core PM NMI Mask Register */
+ u8 res0080[4];
+ __be32 ctbenr; /* 0x0084 Core Time Base Enable Register */
+ u8 res0088[4];
+ __be32 ctbckselr; /* 0x008c Core Time Base Clock Select Register */
+ u8 res0090[4];
+ __be32 ctbhltcr; /* 0x0094 Core Time Base Halt Control Register */
+ u8 res0098[4];
+ __be32 cmcpmaskcr; /* 0x00a4 Core Machine Check Mask Register */
+};
+
+struct ccsr_rcpm_v2 {
+ u8 res_00[12];
+ u32 tph10sr0; /* Thread PH10 Status Register */
+ u8 res_10[12];
+ u32 tph10setr0; /* Thread PH10 Set Control Register */
+ u8 res_20[12];
+ u32 tph10clrr0; /* Thread PH10 Clear Control Register */
+ u8 res_30[12];
+ u32 tph10psr0; /* Thread PH10 Previous Status Register */
+ u8 res_40[12];
+ u32 twaitsr0; /* Thread Wait Status Register */
+ u8 res_50[96];
+ u32 pcph15sr; /* Physical Core PH15 Status Register */
+ u32 pcph15setr; /* Physical Core PH15 Set Control Register */
+ u32 pcph15clrr; /* Physical Core PH15 Clear Control Register */
+ u32 pcph15psr; /* Physical Core PH15 Prev Status Register */
+ u8 res_c0[16];
+ u32 pcph20sr; /* Physical Core PH20 Status Register */
+ u32 pcph20setr; /* Physical Core PH20 Set Control Register */
+ u32 pcph20clrr; /* Physical Core PH20 Clear Control Register */
+ u32 pcph20psr; /* Physical Core PH20 Prev Status Register */
+ u32 pcpw20sr; /* Physical Core PW20 Status Register */
+ u8 res_e0[12];
+ u32 pcph30sr; /* Physical Core PH30 Status Register */
+ u32 pcph30setr; /* Physical Core PH30 Set Control Register */
+ u32 pcph30clrr; /* Physical Core PH30 Clear Control Register */
+ u32 pcph30psr; /* Physical Core PH30 Prev Status Register */
+ u8 res_100[32];
+ u32 ippwrgatecr; /* IP Power Gating Control Register */
+ u8 res_124[12];
+ u32 powmgtcsr; /* Power Management Control & Status Reg */
+#define RCPM_POWMGTCSR_LPM20_RQ 0x00100000
+#define RCPM_POWMGTCSR_LPM20_ST 0x00000200
+#define RCPM_POWMGTCSR_P_LPM20_ST 0x00000100
+ u8 res_134[12];
+ u32 ippdexpcr[4]; /* IP Powerdown Exception Control Reg */
+ u8 res_150[12];
+ u32 tpmimr0; /* Thread PM Interrupt Mask Reg */
+ u8 res_160[12];
+ u32 tpmcimr0; /* Thread PM Crit Interrupt Mask Reg */
+ u8 res_170[12];
+ u32 tpmmcmr0; /* Thread PM Machine Check Interrupt Mask Reg */
+ u8 res_180[12];
+ u32 tpmnmimr0; /* Thread PM NMI Mask Reg */
+ u8 res_190[12];
+ u32 tmcpmaskcr0; /* Thread Machine Check Mask Control Reg */
+ u32 pctbenr; /* Physical Core Time Base Enable Reg */
+ u32 pctbclkselr; /* Physical Core Time Base Clock Select */
+ u32 tbclkdivr; /* Time Base Clock Divider Register */
+ u8 res_1ac[4];
+ u32 ttbhltcr[4]; /* Thread Time Base Halt Control Register */
+ u32 clpcl10sr; /* Cluster PCL10 Status Register */
+ u32 clpcl10setr; /* Cluster PCL30 Set Control Register */
+ u32 clpcl10clrr; /* Cluster PCL30 Clear Control Register */
+ u32 clpcl10psr; /* Cluster PCL30 Prev Status Register */
+ u32 cddslpsetr; /* Core Domain Deep Sleep Set Register */
+ u32 cddslpclrr; /* Core Domain Deep Sleep Clear Register */
+ u32 cdpwroksetr; /* Core Domain Power OK Set Register */
+ u32 cdpwrokclrr; /* Core Domain Power OK Clear Register */
+ u32 cdpwrensr; /* Core Domain Power Enable Status Register */
+ u32 cddslsr; /* Core Domain Deep Sleep Status Register */
+ u8 res_1e8[8];
+ u32 dslpcntcr[8]; /* Deep Sleep Counter Cfg Register */
+ u8 res_300[3568];
+};
+
#endif
#endif
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index c17aae8..54d8843 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -8,6 +8,7 @@ menuconfig FSL_SOC_BOOKE
select FSL_PCI if PCI
select SERIAL_8250_EXTENDED if SERIAL_8250
select SERIAL_8250_SHARE_IRQ if SERIAL_8250
+ select FSL_CORENET_RCPM if PPC_E500MC
default y
if FSL_SOC_BOOKE
diff --git a/arch/powerpc/platforms/85xx/corenet_generic.c b/arch/powerpc/platforms/85xx/corenet_generic.c
index b756f3d..3fdf9f3 100644
--- a/arch/powerpc/platforms/85xx/corenet_generic.c
+++ b/arch/powerpc/platforms/85xx/corenet_generic.c
@@ -56,6 +56,8 @@ void __init corenet_gen_setup_arch(void)
swiotlb_detect_4g();
+ fsl_rcpm_init();
+
pr_info("%s board from Freescale Semiconductor\n", ppc_md.name);
}
diff --git a/arch/powerpc/sysdev/Kconfig b/arch/powerpc/sysdev/Kconfig
index 7baa70d..f6e7cde 100644
--- a/arch/powerpc/sysdev/Kconfig
+++ b/arch/powerpc/sysdev/Kconfig
@@ -34,3 +34,8 @@ config SCOM_DEBUGFS
config GE_FPGA
bool
default n
+
+config FSL_CORENET_RCPM
+ bool
+ help
+ This option enables support for RCPM (Run Control/Power Management).
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index f67ac90..a6ada64 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o
obj-$(CONFIG_FSL_SOC) += fsl_soc.o fsl_mpic_err.o
obj-$(CONFIG_FSL_PCI) += fsl_pci.o $(fsl-msi-obj-y)
obj-$(CONFIG_FSL_PMC) += fsl_pmc.o
+obj-$(CONFIG_FSL_CORENET_RCPM) += fsl_rcpm.o
obj-$(CONFIG_FSL_LBC) += fsl_lbc.o
obj-$(CONFIG_FSL_IFC) += fsl_ifc.o
obj-$(CONFIG_FSL_GTM) += fsl_gtm.o
diff --git a/arch/powerpc/sysdev/fsl_rcpm.c b/arch/powerpc/sysdev/fsl_rcpm.c
new file mode 100644
index 0000000..493fcae
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_rcpm.c
@@ -0,0 +1,315 @@
+/*
+ * RCPM(Run Control/Power Management) support
+ *
+ * Copyright 2012-2014 Freescale Semiconductor Inc.
+ *
+ * Author: Chenhui Zhao <chenhui.zhao@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/of_address.h>
+#include <linux/export.h>
+
+#include <asm/io.h>
+#include <asm/fsl_guts.h>
+#include <asm/cputhreads.h>
+#include <sysdev/fsl_soc.h>
+
+const struct fsl_pm_ops *qoriq_pm_ops;
+
+static struct ccsr_rcpm_v1 __iomem *rcpm_v1_regs;
+static struct ccsr_rcpm_v2 __iomem *rcpm_v2_regs;
+
+static void rcpm_v1_irq_mask(int cpu)
+{
+ int hw_cpu = get_hard_smp_processor_id(cpu);
+ unsigned int mask = 1 << hw_cpu;
+
+ setbits32(&rcpm_v1_regs->cpmimr, mask);
+ setbits32(&rcpm_v1_regs->cpmcimr, mask);
+ setbits32(&rcpm_v1_regs->cpmmcmr, mask);
+ setbits32(&rcpm_v1_regs->cpmnmimr, mask);
+}
+
+static void rcpm_v1_irq_unmask(int cpu)
+{
+ int hw_cpu = get_hard_smp_processor_id(cpu);
+ unsigned int mask = 1 << hw_cpu;
+
+ clrbits32(&rcpm_v1_regs->cpmimr, mask);
+ clrbits32(&rcpm_v1_regs->cpmcimr, mask);
+ clrbits32(&rcpm_v1_regs->cpmmcmr, mask);
+ clrbits32(&rcpm_v1_regs->cpmnmimr, mask);
+}
+
+static void rcpm_v1_set_ip_power(int enable, u32 mask)
+{
+ if (enable)
+ setbits32(&rcpm_v1_regs->ippdexpcr, mask);
+ else
+ clrbits32(&rcpm_v1_regs->ippdexpcr, mask);
+}
+
+static void rcpm_v1_cpu_enter_state(int cpu, int state)
+{
+ unsigned int hw_cpu = get_hard_smp_processor_id(cpu);
+ unsigned int mask = 1 << hw_cpu;
+
+ switch (state) {
+ case E500_PM_PH10:
+ setbits32(&rcpm_v1_regs->cdozcr, mask);
+ break;
+ case E500_PM_PH15:
+ setbits32(&rcpm_v1_regs->cnapcr, mask);
+ break;
+ default:
+ pr_err("Unknown cpu PM state\n");
+ break;
+ }
+}
+
+static void rcpm_v1_cpu_exit_state(int cpu, int state)
+{
+ unsigned int hw_cpu = get_hard_smp_processor_id(cpu);
+ unsigned int mask = 1 << hw_cpu;
+
+ switch (state) {
+ case E500_PM_PH10:
+ clrbits32(&rcpm_v1_regs->cdozcr, mask);
+ break;
+ case E500_PM_PH15:
+ clrbits32(&rcpm_v1_regs->cnapcr, mask);
+ break;
+ default:
+ pr_err("Unknown cpu PM state\n");
+ break;
+ }
+}
+
+static int rcpm_v1_plat_enter_state(int state)
+{
+ u32 *pmcsr_reg = &rcpm_v1_regs->powmgtcsr;
+ int ret = 0;
+ int result;
+
+ switch (state) {
+ case PLAT_PM_SLEEP:
+ setbits32(pmcsr_reg, RCPM_POWMGTCSR_SLP);
+
+ /* At this point, the device is in sleep mode. */
+
+ /* Upon resume, wait for RCPM_POWMGTCSR_SLP bit to be clear. */
+ result = spin_event_timeout(
+ !(in_be32(pmcsr_reg) & RCPM_POWMGTCSR_SLP), 10000, 10);
+ if (!result) {
+ pr_err("%s: timeout waiting for SLP bit to be cleared\n",
+ __func__);
+ ret = -ETIMEDOUT;
+ }
+ break;
+ default:
+ pr_err("Unsupported platform PM state\n");
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static void rcpm_v1_freeze_time_base(int freeze)
+{
+ u32 *tben_reg = &rcpm_v1_regs->ctbenr;
+ static u32 mask;
+
+ if (freeze) {
+ mask = in_be32(tben_reg);
+ clrbits32(tben_reg, mask);
+ } else {
+ setbits32(tben_reg, mask);
+ }
+
+ /* read back to push the previous write */
+ in_be32(tben_reg);
+}
+
+static void rcpm_v2_freeze_time_base(int freeze)
+{
+ u32 *tben_reg = &rcpm_v2_regs->pctbenr;
+ static u32 mask;
+
+ if (freeze) {
+ mask = in_be32(tben_reg);
+ clrbits32(tben_reg, mask);
+ } else {
+ setbits32(tben_reg, mask);
+ }
+
+ /* read back to push the previous write */
+ in_be32(tben_reg);
+}
+
+static void rcpm_v2_irq_mask(int cpu)
+{
+ int hw_cpu = get_hard_smp_processor_id(cpu);
+ unsigned int mask = 1 << hw_cpu;
+
+ setbits32(&rcpm_v2_regs->tpmimr0, mask);
+ setbits32(&rcpm_v2_regs->tpmcimr0, mask);
+ setbits32(&rcpm_v2_regs->tpmmcmr0, mask);
+ setbits32(&rcpm_v2_regs->tpmnmimr0, mask);
+}
+
+static void rcpm_v2_irq_unmask(int cpu)
+{
+ int hw_cpu = get_hard_smp_processor_id(cpu);
+ unsigned int mask = 1 << hw_cpu;
+
+ clrbits32(&rcpm_v2_regs->tpmimr0, mask);
+ clrbits32(&rcpm_v2_regs->tpmcimr0, mask);
+ clrbits32(&rcpm_v2_regs->tpmmcmr0, mask);
+ clrbits32(&rcpm_v2_regs->tpmnmimr0, mask);
+}
+
+static void rcpm_v2_set_ip_power(int enable, u32 mask)
+{
+ if (enable)
+ /* enable power of IP blocks in deep sleep mode */
+ setbits32(&rcpm_v2_regs->ippdexpcr[0], mask);
+ else
+ clrbits32(&rcpm_v2_regs->ippdexpcr[0], mask);
+}
+
+static void rcpm_v2_cpu_enter_state(int cpu, int state)
+{
+ unsigned int hw_cpu = get_hard_smp_processor_id(cpu);
+ u32 mask = 1 << cpu_core_index_of_thread(hw_cpu);
+
+ switch (state) {
+ case E500_PM_PH10:
+ /* one bit corresponds to one thread for PH10 of 6500 */
+ setbits32(&rcpm_v2_regs->tph10setr0, 1 << hw_cpu);
+ break;
+ case E500_PM_PH15:
+ setbits32(&rcpm_v2_regs->pcph15setr, mask);
+ break;
+ case E500_PM_PH20:
+ setbits32(&rcpm_v2_regs->pcph20setr, mask);
+ break;
+ case E500_PM_PH30:
+ setbits32(&rcpm_v2_regs->pcph30setr, mask);
+ break;
+ default:
+ pr_err("Unsupported cpu PM state\n");
+ }
+}
+
+static void rcpm_v2_cpu_exit_state(int cpu, int state)
+{
+ unsigned int hw_cpu = get_hard_smp_processor_id(cpu);
+ u32 mask = 1 << cpu_core_index_of_thread(hw_cpu);
+
+ switch (state) {
+ case E500_PM_PH10:
+ setbits32(&rcpm_v2_regs->tph10clrr0, 1 << hw_cpu);
+ break;
+ case E500_PM_PH15:
+ setbits32(&rcpm_v2_regs->pcph15clrr, mask);
+ break;
+ case E500_PM_PH20:
+ setbits32(&rcpm_v2_regs->pcph20clrr, mask);
+ break;
+ case E500_PM_PH30:
+ setbits32(&rcpm_v2_regs->pcph30clrr, mask);
+ break;
+ default:
+ pr_err("Unsupported cpu PM state\n");
+ }
+}
+
+static int rcpm_v2_plat_enter_state(int state)
+{
+ u32 *pmcsr_reg = &rcpm_v2_regs->powmgtcsr;
+ int ret = 0;
+ int result;
+
+ switch (state) {
+ case PLAT_PM_LPM20:
+ /* clear previous LPM20 status */
+ setbits32(pmcsr_reg, RCPM_POWMGTCSR_P_LPM20_ST);
+ /* enter LPM20 status */
+ setbits32(pmcsr_reg, RCPM_POWMGTCSR_LPM20_RQ);
+
+ /* At this point, the device is in LPM20 status. */
+
+ /* resume ... */
+ result = spin_event_timeout(
+ !(in_be32(pmcsr_reg) & RCPM_POWMGTCSR_LPM20_ST), 10000, 10);
+ if (!result) {
+ pr_err("%s: timeout waiting for LPM20 bit to be cleared\n",
+ __func__);
+ ret = -ETIMEDOUT;
+ }
+ break;
+ default:
+ pr_err("Unsupported platform PM state\n");
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static const struct fsl_pm_ops qoriq_rcpm_v1_ops = {
+ .irq_mask = rcpm_v1_irq_mask,
+ .irq_unmask = rcpm_v1_irq_unmask,
+ .cpu_enter_state = rcpm_v1_cpu_enter_state,
+ .cpu_exit_state = rcpm_v1_cpu_exit_state,
+ .plat_enter_state = rcpm_v1_plat_enter_state,
+ .set_ip_power = rcpm_v1_set_ip_power,
+ .freeze_time_base = rcpm_v1_freeze_time_base,
+};
+
+static const struct fsl_pm_ops qoriq_rcpm_v2_ops = {
+ .irq_mask = rcpm_v2_irq_mask,
+ .irq_unmask = rcpm_v2_irq_unmask,
+ .cpu_enter_state = rcpm_v2_cpu_enter_state,
+ .cpu_exit_state = rcpm_v2_cpu_exit_state,
+ .plat_enter_state = rcpm_v2_plat_enter_state,
+ .set_ip_power = rcpm_v2_set_ip_power,
+ .freeze_time_base = rcpm_v2_freeze_time_base,
+};
+
+int fsl_rcpm_init(void)
+{
+ struct device_node *np;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,qoriq-rcpm-2.0");
+ if (np) {
+ rcpm_v2_regs = of_iomap(np, 0);
+ of_node_put(np);
+ if (!rcpm_v2_regs)
+ return -ENOMEM;
+
+ qoriq_pm_ops = &qoriq_rcpm_v2_ops;
+
+ } else {
+ np = of_find_compatible_node(NULL, NULL, "fsl,qoriq-rcpm-1.0");
+ if (np) {
+ rcpm_v1_regs = of_iomap(np, 0);
+ of_node_put(np);
+ if (!rcpm_v1_regs)
+ return -ENOMEM;
+
+ qoriq_pm_ops = &qoriq_rcpm_v1_ops;
+
+ } else {
+ pr_err("%s: can't find the rcpm node.\n", __func__);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h
index 4c5a19e..9b9a34a 100644
--- a/arch/powerpc/sysdev/fsl_soc.h
+++ b/arch/powerpc/sysdev/fsl_soc.h
@@ -45,5 +45,29 @@ extern struct platform_diu_data_ops diu_ops;
void fsl_hv_restart(char *cmd);
void fsl_hv_halt(void);
+struct fsl_pm_ops {
+ void (*irq_mask)(int cpu);
+ void (*irq_unmask)(int cpu);
+ void (*cpu_enter_state)(int cpu, int state);
+ void (*cpu_exit_state)(int cpu, int state);
+ int (*plat_enter_state)(int state);
+ void (*freeze_time_base)(int freeze);
+ void (*set_ip_power)(int enable, u32 mask);
+};
+
+extern const struct fsl_pm_ops *qoriq_pm_ops;
+
+#define E500_PM_PH10 1
+#define E500_PM_PH15 2
+#define E500_PM_PH20 3
+#define E500_PM_PH30 4
+#define E500_PM_DOZE E500_PM_PH10
+#define E500_PM_NAP E500_PM_PH15
+
+#define PLAT_PM_SLEEP 20
+#define PLAT_PM_LPM20 30
+
+extern int fsl_rcpm_init(void);
+
#endif
#endif
--
1.7.3
^ permalink raw reply related
* [PATCH 6/9] powerpc/85xx: support sleep feature on QorIQ SoCs with RCPM
From: Chenhui Zhao @ 2014-03-07 4:58 UTC (permalink / raw)
To: linuxppc-dev; +Cc: scottwood, linux-kernel, Jason.Jin
In-Reply-To: <1394168285-32275-1-git-send-email-chenhui.zhao@freescale.com>
In sleep mode, the clocks of e500 cores and unused IP blocks is
turned off. The IP blocks which are allowed to wake up the processor
are still running.
The sleep mode is equal to the Standby state in Linux. Use the
command to enter sleep mode:
echo standby > /sys/power/state
Signed-off-by: Chenhui Zhao <chenhui.zhao@freescale.com>
---
arch/powerpc/Kconfig | 4 +-
arch/powerpc/platforms/85xx/Makefile | 3 +
arch/powerpc/platforms/85xx/qoriq_pm.c | 78 ++++++++++++++++++++++++++++++++
3 files changed, 83 insertions(+), 2 deletions(-)
create mode 100644 arch/powerpc/platforms/85xx/qoriq_pm.c
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 05f6323..e1d6510 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -222,7 +222,7 @@ config ARCH_HIBERNATION_POSSIBLE
config ARCH_SUSPEND_POSSIBLE
def_bool y
depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200 || PPC_83xx || \
- (PPC_85xx && !PPC_E500MC) || PPC_86xx || PPC_PSERIES \
+ FSL_SOC_BOOKE || PPC_86xx || PPC_PSERIES \
|| 44x || 40x
config PPC_DCR_NATIVE
@@ -709,7 +709,7 @@ config FSL_PCI
config FSL_PMC
bool
default y
- depends on SUSPEND && (PPC_85xx || PPC_86xx)
+ depends on SUSPEND && (PPC_85xx && !PPC_E500MC || PPC_86xx)
help
Freescale MPC85xx/MPC86xx power management controller support
(suspend/resume). For MPC83xx see platforms/83xx/suspend.c
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
index 25cebe7..7fae817 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -2,6 +2,9 @@
# Makefile for the PowerPC 85xx linux kernel.
#
obj-$(CONFIG_SMP) += smp.o
+ifeq ($(CONFIG_FSL_CORENET_RCPM), y)
+obj-$(CONFIG_SUSPEND) += qoriq_pm.o
+endif
obj-y += common.o
diff --git a/arch/powerpc/platforms/85xx/qoriq_pm.c b/arch/powerpc/platforms/85xx/qoriq_pm.c
new file mode 100644
index 0000000..915b13b
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/qoriq_pm.c
@@ -0,0 +1,78 @@
+/*
+ * Support Power Management feature
+ *
+ * Copyright 2014 Freescale Semiconductor Inc.
+ *
+ * Author: Chenhui Zhao <chenhui.zhao@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/suspend.h>
+#include <linux/of_platform.h>
+
+#include <sysdev/fsl_soc.h>
+
+#define FSL_SLEEP 0x1
+#define FSL_DEEP_SLEEP 0x2
+
+/* specify the sleep state of the present platform */
+int sleep_pm_state;
+/* supported sleep modes by the present platform */
+static unsigned int sleep_modes;
+
+static int qoriq_suspend_enter(suspend_state_t state)
+{
+ int ret = 0;
+
+ switch (state) {
+ case PM_SUSPEND_STANDBY:
+
+ if (cur_cpu_spec->cpu_flush_caches)
+ cur_cpu_spec->cpu_flush_caches();
+
+ ret = qoriq_pm_ops->plat_enter_state(sleep_pm_state);
+
+ break;
+
+ default:
+ ret = -EINVAL;
+
+ }
+
+ return ret;
+}
+
+static int qoriq_suspend_valid(suspend_state_t state)
+{
+ if (state == PM_SUSPEND_STANDBY && (sleep_modes & FSL_SLEEP))
+ return 1;
+
+ return 0;
+}
+
+static const struct platform_suspend_ops qoriq_suspend_ops = {
+ .valid = qoriq_suspend_valid,
+ .enter = qoriq_suspend_enter,
+};
+
+static int __init qoriq_suspend_init(void)
+{
+ struct device_node *np;
+
+ sleep_modes = FSL_SLEEP;
+ sleep_pm_state = PLAT_PM_SLEEP;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,qoriq-rcpm-2.0");
+ if (np)
+ sleep_pm_state = PLAT_PM_LPM20;
+
+ suspend_set_ops(&qoriq_suspend_ops);
+
+ return 0;
+}
+arch_initcall(qoriq_suspend_init);
--
1.7.3
^ permalink raw reply related
* [PATCH 7/9] fsl: add EPU FSM configuration for deep sleep
From: Chenhui Zhao @ 2014-03-07 4:58 UTC (permalink / raw)
To: linuxppc-dev; +Cc: scottwood, linux-kernel, Jason.Jin
In-Reply-To: <1394168285-32275-1-git-send-email-chenhui.zhao@freescale.com>
From: Hongbo Zhang <hongbo.zhang@freescale.com>
In the last stage of deep sleep, software will trigger a Finite
State Machine (FSM) to control the hardware precedure, such as
board isolation, killing PLLs, removing power, and so on.
When the system is waked up by an interrupt, the FSM controls the
hardware to complete the early resume precedure.
This patch configure the EPU FSM preparing for deep sleep.
Signed-off-by: Hongbo Zhang <hongbo.zhang@freescale.com>
Signed-off-by: Chenhui Zhao <chenhui.zhao@freescale.com>
---
arch/powerpc/platforms/85xx/Kconfig | 1 +
arch/powerpc/sysdev/fsl_soc.h | 3 +
drivers/platform/Kconfig | 4 +
drivers/platform/Makefile | 1 +
drivers/platform/fsl/Kconfig | 10 +
drivers/platform/fsl/Makefile | 5 +
drivers/platform/fsl/sleep_fsm.c | 415 +++++++++++++++++++++++++++++=
++++++
7 files changed, 439 insertions(+), 0 deletions(-)
create mode 100644 drivers/platform/fsl/Kconfig
create mode 100644 drivers/platform/fsl/Makefile
create mode 100644 drivers/platform/fsl/sleep_fsm.c
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms=
/85xx/Kconfig
index 54d8843..27e2174 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -261,6 +261,7 @@ config CORENET_GENERIC
select GPIO_MPC8XXX
select HAS_RAPIDIO
select PPC_EPAPR_HV_PIC
+ select FSL_SLEEP_FSM if SUSPEND
help
This option enables support for the FSL CoreNet based boards.
For 32bit kernel, the following boards are supported:
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.=
h
index 9b9a34a..eb83a30 100644
--- a/arch/powerpc/sysdev/fsl_soc.h
+++ b/arch/powerpc/sysdev/fsl_soc.h
@@ -69,5 +69,8 @@ extern const struct fsl_pm_ops *qoriq_pm_ops;
=20
extern int fsl_rcpm_init(void);
=20
+extern void fsl_dp_fsm_setup(void *dcsr_base);
+extern void fsl_dp_fsm_clean(void *dcsr_base);
+
#endif
#endif
diff --git a/drivers/platform/Kconfig b/drivers/platform/Kconfig
index 09fde58..6539e6d 100644
--- a/drivers/platform/Kconfig
+++ b/drivers/platform/Kconfig
@@ -6,3 +6,7 @@ source "drivers/platform/goldfish/Kconfig"
endif
=20
source "drivers/platform/chrome/Kconfig"
+
+if FSL_SOC
+source "drivers/platform/fsl/Kconfig"
+endif
diff --git a/drivers/platform/Makefile b/drivers/platform/Makefile
index 3656b7b..37c6f72 100644
--- a/drivers/platform/Makefile
+++ b/drivers/platform/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_X86) +=3D x86/
obj-$(CONFIG_OLPC) +=3D olpc/
obj-$(CONFIG_GOLDFISH) +=3D goldfish/
obj-$(CONFIG_CHROME_PLATFORMS) +=3D chrome/
+obj-$(CONFIG_FSL_SOC) +=3D fsl/
diff --git a/drivers/platform/fsl/Kconfig b/drivers/platform/fsl/Kconfig
new file mode 100644
index 0000000..72ed053
--- /dev/null
+++ b/drivers/platform/fsl/Kconfig
@@ -0,0 +1,10 @@
+#
+# Freescale Specific Power Management Drivers
+#
+
+config FSL_SLEEP_FSM
+ bool
+ help
+ This driver configures a hardware FSM (Finite State Machine) for deep=
sleep.
+ The FSM is used to finish clean-ups at the last stage of system enter=
ing deep
+ sleep, and also wakes up system when a wake up event happens.
diff --git a/drivers/platform/fsl/Makefile b/drivers/platform/fsl/Makefil=
e
new file mode 100644
index 0000000..d99ca0e
--- /dev/null
+++ b/drivers/platform/fsl/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for linux/drivers/platform/fsl
+# Freescale Specific Power Management Drivers
+#
+obj-$(CONFIG_FSL_SLEEP_FSM) +=3D sleep_fsm.o
diff --git a/drivers/platform/fsl/sleep_fsm.c b/drivers/platform/fsl/slee=
p_fsm.c
new file mode 100644
index 0000000..1033332
--- /dev/null
+++ b/drivers/platform/fsl/sleep_fsm.c
@@ -0,0 +1,415 @@
+/*
+ * Freescale deep sleep FSM (finite-state machine) configuration
+ *
+ * Copyright 2014 Freescale Semiconductor Inc.
+ *
+ * Author: Hongbo Zhang <hongbo.zhang@freescale.com>
+ * Chenhui Zhao <chenhui.zhao@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify=
it
+ * under the terms of the GNU General Public License as published by =
the
+ * Free Software Foundation; either version 2 of the License, or (at y=
our
+ * option) any later version.
+ */
+
+#include <linux/io.h>
+#include <linux/types.h>
+
+#define FSL_STRIDE_4B 4
+#define FSL_STRIDE_8B 8
+
+/* Event Processor Global Control Register */
+#define EPGCR 0x000
+
+/* Event Processor EVT Pin Control Registers */
+#define EPEVTCR0 0x050
+#define EPEVTCR1 0x054
+#define EPEVTCR2 0x058
+#define EPEVTCR3 0x05C
+#define EPEVTCR4 0x060
+#define EPEVTCR5 0x064
+#define EPEVTCR6 0x068
+#define EPEVTCR7 0x06C
+#define EPEVTCR8 0x070
+#define EPEVTCR9 0x074
+
+/* Event Processor Crosstrigger Control Register */
+#define EPXTRIGCR 0x090
+
+/* Event Processor Input Mux Control Registers */
+#define EPIMCR0 0x100
+#define EPIMCR1 0x104
+#define EPIMCR2 0x108
+#define EPIMCR3 0x10C
+#define EPIMCR4 0x110
+#define EPIMCR5 0x114
+#define EPIMCR6 0x118
+#define EPIMCR7 0x11C
+#define EPIMCR8 0x120
+#define EPIMCR9 0x124
+#define EPIMCR10 0x128
+#define EPIMCR11 0x12C
+#define EPIMCR12 0x130
+#define EPIMCR13 0x134
+#define EPIMCR14 0x138
+#define EPIMCR15 0x13C
+#define EPIMCR16 0x140
+#define EPIMCR17 0x144
+#define EPIMCR18 0x148
+#define EPIMCR19 0x14C
+#define EPIMCR20 0x150
+#define EPIMCR21 0x154
+#define EPIMCR22 0x158
+#define EPIMCR23 0x15C
+#define EPIMCR24 0x160
+#define EPIMCR25 0x164
+#define EPIMCR26 0x168
+#define EPIMCR27 0x16C
+#define EPIMCR28 0x170
+#define EPIMCR29 0x174
+#define EPIMCR30 0x178
+#define EPIMCR31 0x17C
+
+/* Event Processor SCU Mux Control Registers */
+#define EPSMCR0 0x200
+#define EPSMCR1 0x208
+#define EPSMCR2 0x210
+#define EPSMCR3 0x218
+#define EPSMCR4 0x220
+#define EPSMCR5 0x228
+#define EPSMCR6 0x230
+#define EPSMCR7 0x238
+#define EPSMCR8 0x240
+#define EPSMCR9 0x248
+#define EPSMCR10 0x250
+#define EPSMCR11 0x258
+#define EPSMCR12 0x260
+#define EPSMCR13 0x268
+#define EPSMCR14 0x270
+#define EPSMCR15 0x278
+
+/* Event Processor Event Control Registers */
+#define EPECR0 0x300
+#define EPECR1 0x304
+#define EPECR2 0x308
+#define EPECR3 0x30C
+#define EPECR4 0x310
+#define EPECR5 0x314
+#define EPECR6 0x318
+#define EPECR7 0x31C
+#define EPECR8 0x320
+#define EPECR9 0x324
+#define EPECR10 0x328
+#define EPECR11 0x32C
+#define EPECR12 0x330
+#define EPECR13 0x334
+#define EPECR14 0x338
+#define EPECR15 0x33C
+
+/* Event Processor Action Control Registers */
+#define EPACR0 0x400
+#define EPACR1 0x404
+#define EPACR2 0x408
+#define EPACR3 0x40C
+#define EPACR4 0x410
+#define EPACR5 0x414
+#define EPACR6 0x418
+#define EPACR7 0x41C
+#define EPACR8 0x420
+#define EPACR9 0x424
+#define EPACR10 0x428
+#define EPACR11 0x42C
+#define EPACR12 0x430
+#define EPACR13 0x434
+#define EPACR14 0x438
+#define EPACR15 0x43C
+
+/* Event Processor Counter Control Registers */
+#define EPCCR0 0x800
+#define EPCCR1 0x804
+#define EPCCR2 0x808
+#define EPCCR3 0x80C
+#define EPCCR4 0x810
+#define EPCCR5 0x814
+#define EPCCR6 0x818
+#define EPCCR7 0x81C
+#define EPCCR8 0x820
+#define EPCCR9 0x824
+#define EPCCR10 0x828
+#define EPCCR11 0x82C
+#define EPCCR12 0x830
+#define EPCCR13 0x834
+#define EPCCR14 0x838
+#define EPCCR15 0x83C
+
+/* Event Processor Counter Compare Registers */
+#define EPCMPR0 0x900
+#define EPCMPR1 0x904
+#define EPCMPR2 0x908
+#define EPCMPR3 0x90C
+#define EPCMPR4 0x910
+#define EPCMPR5 0x914
+#define EPCMPR6 0x918
+#define EPCMPR7 0x91C
+#define EPCMPR8 0x920
+#define EPCMPR9 0x924
+#define EPCMPR10 0x928
+#define EPCMPR11 0x92C
+#define EPCMPR12 0x930
+#define EPCMPR13 0x934
+#define EPCMPR14 0x938
+#define EPCMPR15 0x93C
+
+/* Event Processor Counter Register */
+#define EPCTR0 0xA00
+#define EPCTR1 0xA04
+#define EPCTR2 0xA08
+#define EPCTR3 0xA0C
+#define EPCTR4 0xA10
+#define EPCTR5 0xA14
+#define EPCTR6 0xA18
+#define EPCTR7 0xA1C
+#define EPCTR8 0xA20
+#define EPCTR9 0xA24
+#define EPCTR10 0xA28
+#define EPCTR11 0xA2C
+#define EPCTR12 0xA30
+#define EPCTR13 0xA34
+#define EPCTR14 0xA38
+#define EPCTR15 0xA3C
+#define EPCTR16 0xA40
+#define EPCTR17 0xA44
+#define EPCTR18 0xA48
+#define EPCTR19 0xA4C
+#define EPCTR20 0xA50
+#define EPCTR21 0xA54
+#define EPCTR22 0xA58
+#define EPCTR23 0xA5C
+#define EPCTR24 0xA60
+#define EPCTR25 0xA64
+#define EPCTR26 0xA68
+#define EPCTR27 0xA6C
+#define EPCTR28 0xA70
+#define EPCTR29 0xA74
+#define EPCTR30 0xA78
+#define EPCTR31 0xA7C
+
+/* NPC triggered Memory-Mapped Access Registers */
+#define NCR 0x000
+#define MCCR1 0x0CC
+#define MCSR1 0x0D0
+#define MMAR1LO 0x0D4
+#define MMAR1HI 0x0D8
+#define MMDR1 0x0DC
+#define MCSR2 0x0E0
+#define MMAR2LO 0x0E4
+#define MMAR2HI 0x0E8
+#define MMDR2 0x0EC
+#define MCSR3 0x0F0
+#define MMAR3LO 0x0F4
+#define MMAR3HI 0x0F8
+#define MMDR3 0x0FC
+
+/* RCPM Core State Action Control Register 0 */
+#define CSTTACR0 0xB00
+
+/* RCPM Core Group 1 Configuration Register 0 */
+#define CG1CR0 0x31C
+
+/* Block offsets */
+#define RCPM_BLOCK_OFFSET 0x00022000
+#define EPU_BLOCK_OFFSET 0x00000000
+#define NPC_BLOCK_OFFSET 0x00001000
+
+static void *g_dcsr_base;
+
+static inline void rcpm_write(u32 offset, u32 val)
+{
+ out_be32(g_dcsr_base + RCPM_BLOCK_OFFSET + offset, val);
+}
+
+static inline void epu_write(u32 offset, u32 val)
+{
+ out_be32(g_dcsr_base + EPU_BLOCK_OFFSET + offset, val);
+}
+
+static inline void npc_write(u32 offset, u32 val)
+{
+ out_be32(g_dcsr_base + NPC_BLOCK_OFFSET + offset, val);
+}
+
+/**
+ * fsl_dp_fsm_setup - Configure EPU's FSM
+ * @dcsr_base: the base address of DCSR registers
+ */
+void fsl_dp_fsm_setup(void *dcsr_base)
+{
+ u32 offset;
+
+ /*
+ * Globle static variable is safe here, becsuse this function is only
+ * called once at the last stage of suspend, when there is only one CPU
+ * running and task switching is also disabled.
+ */
+ g_dcsr_base =3D dcsr_base;
+
+ /* Disable All SCU Actions */
+ for (offset =3D EPACR0; offset <=3D EPACR15; offset +=3D FSL_STRIDE_4B)
+ epu_write(offset, 0);
+
+ /* Clear EPEVTCRn */
+ for (offset =3D EPEVTCR0; offset <=3D EPEVTCR9; offset +=3D FSL_STRIDE_=
4B)
+ epu_write(offset, 0);
+
+ /* Clear Event Processor Global Control Register */
+ epu_write(EPGCR, 0);
+
+ /* Clear EPSMCRn */
+ for (offset =3D EPSMCR0; offset <=3D EPSMCR15; offset +=3D FSL_STRIDE_8=
B)
+ epu_write(offset, 0);
+
+ /* Clear EPCCRn */
+ for (offset =3D EPCCR0; offset <=3D EPCCR15; offset +=3D FSL_STRIDE_4B)
+ epu_write(offset, 0);
+
+ /* Clear EPCMPRn */
+ for (offset =3D EPCMPR0; offset <=3D EPCMPR15; offset +=3D FSL_STRIDE_4=
B)
+ epu_write(offset, 0);
+
+ /*
+ * Clear EPCTRn
+ * Warm Device Reset does NOT reset these counter, so clear them
+ * explicitly. Or, the second time entering deep sleep will fail.
+ */
+ for (offset =3D EPCTR0; offset <=3D EPCTR31; offset +=3D FSL_STRIDE_4B)
+ epu_write(offset, 0);
+
+ /* Clear EPIMCRn */
+ for (offset =3D EPIMCR0; offset <=3D EPIMCR31; offset +=3D FSL_STRIDE_4=
B)
+ epu_write(offset, 0);
+
+ /* Clear EPXTRIGCRn */
+ epu_write(EPXTRIGCR, 0);
+
+ /* Disable all SCUs EPECRn */
+ for (offset =3D EPECR0; offset <=3D EPECR15; offset +=3D FSL_STRIDE_4B)
+ epu_write(offset, 0);
+
+ /* Set up the SCU chaining */
+ epu_write(EPECR15, 0x00000004);
+ epu_write(EPECR14, 0x02000084);
+ epu_write(EPECR13, 0x08000084);
+ epu_write(EPECR12, 0x80000084);
+ epu_write(EPECR11, 0x90000084);
+ epu_write(EPECR10, 0x42000084);
+ epu_write(EPECR9, 0x08000084);
+ epu_write(EPECR8, 0x60000084);
+ epu_write(EPECR7, 0x80000084);
+ epu_write(EPECR6, 0x80000084);
+ epu_write(EPECR5, 0x08000004);
+ epu_write(EPECR4, 0x20000084);
+ epu_write(EPECR3, 0x80000084);
+ epu_write(EPECR2, 0xF0004004);
+
+ /* EVT Pin Configuration. SCU8 triger EVT2, and SCU11 triger EVT9 */
+ epu_write(EPEVTCR2, 0x80000001);
+ epu_write(EPEVTCR9, 0xB0000001);
+
+ /* Configure the EPU Counter Values */
+ epu_write(EPCMPR15, 0x000000FF);
+ epu_write(EPCMPR14, 0x000000FF);
+ epu_write(EPCMPR12, 0x000000FF);
+ epu_write(EPCMPR11, 0x000000FF);
+ epu_write(EPCMPR10, 0x000000FF);
+ epu_write(EPCMPR9, 0x000000FF);
+ epu_write(EPCMPR8, 0x000000FF);
+ epu_write(EPCMPR5, 0x00000020);
+ epu_write(EPCMPR4, 0x000000FF);
+ epu_write(EPCMPR2, 0x000000FF);
+
+ /* Configure the EPU Counters */
+ epu_write(EPCCR15, 0x92840000);
+ epu_write(EPCCR14, 0x92840000);
+ epu_write(EPCCR12, 0x92840000);
+ epu_write(EPCCR11, 0x92840000);
+ epu_write(EPCCR10, 0x92840000);
+ epu_write(EPCCR9, 0x92840000);
+ epu_write(EPCCR8, 0x92840000);
+ epu_write(EPCCR5, 0x92840000);
+ epu_write(EPCCR4, 0x92840000);
+ epu_write(EPCCR2, 0x92840000);
+
+ /* Configure the SCUs Inputs */
+ epu_write(EPSMCR15, 0x76000000);
+ epu_write(EPSMCR14, 0x00000031);
+ epu_write(EPSMCR13, 0x00003100);
+ epu_write(EPSMCR12, 0x7F000000);
+ epu_write(EPSMCR11, 0x31740000);
+ epu_write(EPSMCR10, 0x65000030);
+ epu_write(EPSMCR9, 0x00003000);
+ epu_write(EPSMCR8, 0x64300000);
+ epu_write(EPSMCR7, 0x30000000);
+ epu_write(EPSMCR6, 0x7C000000);
+ epu_write(EPSMCR5, 0x00002E00);
+ epu_write(EPSMCR4, 0x002F0000);
+ epu_write(EPSMCR3, 0x2F000000);
+ epu_write(EPSMCR2, 0x6C700000);
+
+ /* Configure the SCUs Actions */
+ epu_write(EPACR15, 0x02000000);
+ epu_write(EPACR14, 0x04000000);
+ epu_write(EPACR13, 0x06000000);
+ epu_write(EPACR12, 0x00000003);
+ epu_write(EPACR10, 0x00000020);
+ epu_write(EPACR9, 0x0000001C);
+ epu_write(EPACR5, 0x00000040);
+ epu_write(EPACR3, 0x00000080);
+
+ /* Configure the SCUs and Timers Mux */
+ epu_write(EPIMCR31, 0x76000000);
+ epu_write(EPIMCR28, 0x76000000);
+ epu_write(EPIMCR22, 0x6C000000);
+ epu_write(EPIMCR20, 0x48000000);
+ epu_write(EPIMCR16, 0x6A000000);
+ epu_write(EPIMCR12, 0x44000000);
+ epu_write(EPIMCR5, 0x40000000);
+ epu_write(EPIMCR4, 0x44000000);
+
+ /* Configure pulse or level triggers */
+ epu_write(EPXTRIGCR, 0x0000FFDF);
+
+ /* Configure the NPC tMMA registers*/
+ npc_write(NCR, 0x80000000);
+ npc_write(MCCR1, 0);
+ npc_write(MCSR1, 0);
+ npc_write(MMAR1LO, 0);
+ npc_write(MMAR1HI, 0);
+ npc_write(MMDR1, 0);
+ npc_write(MCSR2, 0);
+ npc_write(MMAR2LO, 0);
+ npc_write(MMAR2HI, 0);
+ npc_write(MMDR2, 0);
+ npc_write(MCSR3, 0x80000000);
+ npc_write(MMAR3LO, 0x000E2130);
+ npc_write(MMAR3HI, 0x00030000);
+ npc_write(MMDR3, 0x00020000);
+
+ /* Configure RCPM for detecting Core0=E2=80=99s PH15 state */
+ rcpm_write(CSTTACR0, 0x00001001);
+ rcpm_write(CG1CR0, 0x00000001);
+
+}
+
+void fsl_dp_fsm_clean(void *dcsr_base)
+{
+
+ epu_write(EPEVTCR2, 0);
+ epu_write(EPEVTCR9, 0);
+
+ epu_write(EPGCR, 0);
+ epu_write(EPECR15, 0);
+
+ rcpm_write(CSTTACR0, 0);
+ rcpm_write(CG1CR0, 0);
+
+}
--=20
1.7.3
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox