booke_cache.c revision 1.4
1/*	$NetBSD: booke_cache.c,v 1.4 2011/06/29 21:53:10 dholland Exp $	*/
2/*-
3 * Copyright (c) 2010, 2011 The NetBSD Foundation, Inc.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to The NetBSD Foundation
7 * by Raytheon BBN Technologies Corp and Defense Advanced Research Projects
8 * Agency and which was developed by Matt Thomas of 3am Software Foundry.
9 *
10 * This material is based upon work supported by the Defense Advanced Research
11 * Projects Agency and Space and Naval Warfare Systems Center, Pacific, under
12 * Contract No. N66001-09-C-2073.
13 * Approved for Public Release, Distribution Unlimited
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 *    notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 *    notice, this list of conditions and the following disclaimer in the
22 *    documentation and/or other materials provided with the distribution.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
25 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
27 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
28 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36/*
37 *
38 */
39#include <sys/cdefs.h>
40
41__KERNEL_RCSID(0, "$NetBSD: booke_cache.c,v 1.4 2011/06/29 21:53:10 dholland Exp $");
42
43#include <sys/param.h>
44#include <sys/cpu.h>
45#include <sys/atomic.h>
46
47enum cache_op { OP_DCBF, OP_DCBST, OP_DCBI, OP_DCBZ, OP_DCBA, OP_ICBI };
48
49static void inline
50dcbf(vaddr_t va, vsize_t off)
51{
52	__asm volatile("dcbf\t%0,%1" : : "b" (va), "r" (off));
53}
54
55static void inline
56dcbst(vaddr_t va, vsize_t off)
57{
58	__asm volatile("dcbst\t%0,%1" : : "b" (va), "r" (off));
59}
60
61static void inline
62dcbi(vaddr_t va, vsize_t off)
63{
64	__asm volatile("dcbi\t%0,%1" : : "b" (va), "r" (off));
65}
66
67static void inline
68dcbz(vaddr_t va, vsize_t off)
69{
70	__asm volatile("dcbz\t%0,%1" : : "b" (va), "r" (off));
71}
72
73static void inline
74dcba(vaddr_t va, vsize_t off)
75{
76	__asm volatile("dcba\t%0,%1" : : "b" (va), "r" (off));
77}
78
79static void inline
80icbi(vaddr_t va, vsize_t off)
81{
82	__asm volatile("icbi\t%0,%1" : : "b" (va), "r" (off));
83}
84
85static inline void
86cache_op(vaddr_t va, vsize_t len, vsize_t line_size, enum cache_op op)
87{
88	KASSERT(line_size > 0);
89
90	if (len == 0)
91		return;
92
93	/* Make sure we flush all cache lines */
94	len += va & (line_size - 1);
95	va &= -line_size;
96
97	for (vsize_t i = 0; i < len; i += line_size) {
98		switch (op) {
99		case OP_DCBF: dcbf(va, i); break;
100		case OP_DCBST: dcbst(va, i); break;
101		case OP_DCBI: dcbi(va, i); break;
102		case OP_DCBZ: dcbz(va, i); break;
103		case OP_DCBA: dcba(va, i); break;
104		case OP_ICBI: icbi(va, i); break;
105		}
106	}
107	if (op != OP_ICBI)
108		membar_producer();
109}
110
111void
112dcache_wb_page(vaddr_t va)
113{
114	cache_op(va, PAGE_SIZE, curcpu()->ci_ci.dcache_line_size, OP_DCBST);
115}
116
117void
118dcache_wbinv_page(vaddr_t va)
119{
120	cache_op(va, PAGE_SIZE, curcpu()->ci_ci.dcache_line_size, OP_DCBF);
121}
122
123void
124dcache_inv_page(vaddr_t va)
125{
126	cache_op(va, PAGE_SIZE, curcpu()->ci_ci.dcache_line_size, OP_DCBI);
127}
128
129void
130dcache_zero_page(vaddr_t va)
131{
132	cache_op(va, PAGE_SIZE, curcpu()->ci_ci.dcache_line_size, OP_DCBZ);
133}
134
135void
136icache_inv_page(vaddr_t va)
137{
138	membar_sync();
139	cache_op(va, PAGE_SIZE, curcpu()->ci_ci.icache_line_size, OP_ICBI);
140	membar_sync();
141	/* synchronizing instruction will be the rfi to user mode */
142}
143
144void
145dcache_wb(vaddr_t va, vsize_t len)
146{
147	cache_op(va, len, curcpu()->ci_ci.dcache_line_size, OP_DCBST);
148}
149
150void
151dcache_wbinv(vaddr_t va, vsize_t len)
152{
153	cache_op(va, len, curcpu()->ci_ci.dcache_line_size, OP_DCBF);
154}
155
156void
157dcache_inv(vaddr_t va, vsize_t len)
158{
159	cache_op(va, len, curcpu()->ci_ci.dcache_line_size, OP_DCBI);
160}
161
162void
163icache_inv(vaddr_t va, vsize_t len)
164{
165	membar_sync();
166	cache_op(va, len, curcpu()->ci_ci.icache_line_size, OP_ICBI);
167	membar_sync();
168}
169