aboutsummaryrefslogtreecommitdiff
path: root/drivers/dma/dmatest.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/dma/dmatest.c')
-rw-r--r--drivers/dma/dmatest.c986
1 files changed, 986 insertions, 0 deletions
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
new file mode 100644
index 00000000000..e27cec25c59
--- /dev/null
+++ b/drivers/dma/dmatest.c
@@ -0,0 +1,986 @@
+/*
+ * DMA Engine test module
+ *
+ * Copyright (C) 2007 Atmel Corporation
+ * Copyright (C) 2013 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/freezer.h>
+#include <linux/init.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+#include <linux/wait.h>
+
+static unsigned int test_buf_size = 16384;
+module_param(test_buf_size, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(test_buf_size, "Size of the memcpy test buffer");
+
+static char test_channel[20];
+module_param_string(channel, test_channel, sizeof(test_channel),
+ S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(channel, "Bus ID of the channel to test (default: any)");
+
+static char test_device[32];
+module_param_string(device, test_device, sizeof(test_device),
+ S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(device, "Bus ID of the DMA Engine to test (default: any)");
+
+static unsigned int threads_per_chan = 1;
+module_param(threads_per_chan, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(threads_per_chan,
+ "Number of threads to start per channel (default: 1)");
+
+static unsigned int max_channels;
+module_param(max_channels, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(max_channels,
+ "Maximum number of channels to use (default: all)");
+
+static unsigned int iterations;
+module_param(iterations, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(iterations,
+ "Iterations before stopping test (default: infinite)");
+
+static unsigned int xor_sources = 3;
+module_param(xor_sources, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(xor_sources,
+ "Number of xor source buffers (default: 3)");
+
+static unsigned int pq_sources = 3;
+module_param(pq_sources, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(pq_sources,
+ "Number of p+q source buffers (default: 3)");
+
+static int timeout = 3000;
+module_param(timeout, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(timeout, "Transfer Timeout in msec (default: 3000), "
+ "Pass -1 for infinite timeout");
+
+static bool noverify;
+module_param(noverify, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(noverify, "Disable random data setup and verification");
+
+static bool verbose;
+module_param(verbose, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(verbose, "Enable \"success\" result messages (default: off)");
+
+/**
+ * struct dmatest_params - test parameters.
+ * @buf_size: size of the memcpy test buffer
+ * @channel: bus ID of the channel to test
+ * @device: bus ID of the DMA Engine to test
+ * @threads_per_chan: number of threads to start per channel
+ * @max_channels: maximum number of channels to use
+ * @iterations: iterations before stopping test
+ * @xor_sources: number of xor source buffers
+ * @pq_sources: number of p+q source buffers
+ * @timeout: transfer timeout in msec, -1 for infinite timeout
+ */
+struct dmatest_params {
+ unsigned int buf_size;
+ char channel[20];
+ char device[32];
+ unsigned int threads_per_chan;
+ unsigned int max_channels;
+ unsigned int iterations;
+ unsigned int xor_sources;
+ unsigned int pq_sources;
+ int timeout;
+ bool noverify;
+};
+
+/**
+ * struct dmatest_info - test information.
+ * @params: test parameters
+ * @lock: access protection to the fields of this structure
+ */
+static struct dmatest_info {
+ /* Test parameters */
+ struct dmatest_params params;
+
+ /* Internal state */
+ struct list_head channels;
+ unsigned int nr_channels;
+ struct mutex lock;
+ bool did_init;
+} test_info = {
+ .channels = LIST_HEAD_INIT(test_info.channels),
+ .lock = __MUTEX_INITIALIZER(test_info.lock),
+};
+
+static int dmatest_run_set(const char *val, const struct kernel_param *kp);
+static int dmatest_run_get(char *val, const struct kernel_param *kp);
+static struct kernel_param_ops run_ops = {
+ .set = dmatest_run_set,
+ .get = dmatest_run_get,
+};
+static bool dmatest_run;
+module_param_cb(run, &run_ops, &dmatest_run, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(run, "Run the test (default: false)");
+
+/* Maximum amount of mismatched bytes in buffer to print */
+#define MAX_ERROR_COUNT 32
+
+/*
+ * Initialization patterns. All bytes in the source buffer has bit 7
+ * set, all bytes in the destination buffer has bit 7 cleared.
+ *
+ * Bit 6 is set for all bytes which are to be copied by the DMA
+ * engine. Bit 5 is set for all bytes which are to be overwritten by
+ * the DMA engine.
+ *
+ * The remaining bits are the inverse of a counter which increments by
+ * one for each byte address.
+ */
+#define PATTERN_SRC 0x80
+#define PATTERN_DST 0x00
+#define PATTERN_COPY 0x40
+#define PATTERN_OVERWRITE 0x20
+#define PATTERN_COUNT_MASK 0x1f
+
+struct dmatest_thread {
+ struct list_head node;
+ struct dmatest_info *info;
+ struct task_struct *task;
+ struct dma_chan *chan;
+ u8 **srcs;
+ u8 **dsts;
+ enum dma_transaction_type type;
+ bool done;
+};
+
+struct dmatest_chan {
+ struct list_head node;
+ struct dma_chan *chan;
+ struct list_head threads;
+};
+
+static DECLARE_WAIT_QUEUE_HEAD(thread_wait);
+static bool wait;
+
+static bool is_threaded_test_run(struct dmatest_info *info)
+{
+ struct dmatest_chan *dtc;
+
+ list_for_each_entry(dtc, &info->channels, node) {
+ struct dmatest_thread *thread;
+
+ list_for_each_entry(thread, &dtc->threads, node) {
+ if (!thread->done)
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static int dmatest_wait_get(char *val, const struct kernel_param *kp)
+{
+ struct dmatest_info *info = &test_info;
+ struct dmatest_params *params = &info->params;
+
+ if (params->iterations)
+ wait_event(thread_wait, !is_threaded_test_run(info));
+ wait = true;
+ return param_get_bool(val, kp);
+}
+
+static struct kernel_param_ops wait_ops = {
+ .get = dmatest_wait_get,
+ .set = param_set_bool,
+};
+module_param_cb(wait, &wait_ops, &wait, S_IRUGO);
+MODULE_PARM_DESC(wait, "Wait for tests to complete (default: false)");
+
+static bool dmatest_match_channel(struct dmatest_params *params,
+ struct dma_chan *chan)
+{
+ if (params->channel[0] == '\0')
+ return true;
+ return strcmp(dma_chan_name(chan), params->channel) == 0;
+}
+
+static bool dmatest_match_device(struct dmatest_params *params,
+ struct dma_device *device)
+{
+ if (params->device[0] == '\0')
+ return true;
+ return strcmp(dev_name(device->dev), params->device) == 0;
+}
+
+static unsigned long dmatest_random(void)
+{
+ unsigned long buf;
+
+ prandom_bytes(&buf, sizeof(buf));
+ return buf;
+}
+
+static void dmatest_init_srcs(u8 **bufs, unsigned int start, unsigned int len,
+ unsigned int buf_size)
+{
+ unsigned int i;
+ u8 *buf;
+
+ for (; (buf = *bufs); bufs++) {
+ for (i = 0; i < start; i++)
+ buf[i] = PATTERN_SRC | (~i & PATTERN_COUNT_MASK);
+ for ( ; i < start + len; i++)
+ buf[i] = PATTERN_SRC | PATTERN_COPY
+ | (~i & PATTERN_COUNT_MASK);
+ for ( ; i < buf_size; i++)
+ buf[i] = PATTERN_SRC | (~i & PATTERN_COUNT_MASK);
+ buf++;
+ }
+}
+
+static void dmatest_init_dsts(u8 **bufs, unsigned int start, unsigned int len,
+ unsigned int buf_size)
+{
+ unsigned int i;
+ u8 *buf;
+
+ for (; (buf = *bufs); bufs++) {
+ for (i = 0; i < start; i++)
+ buf[i] = PATTERN_DST | (~i & PATTERN_COUNT_MASK);
+ for ( ; i < start + len; i++)
+ buf[i] = PATTERN_DST | PATTERN_OVERWRITE
+ | (~i & PATTERN_COUNT_MASK);
+ for ( ; i < buf_size; i++)
+ buf[i] = PATTERN_DST | (~i & PATTERN_COUNT_MASK);
+ }
+}
+
+static void dmatest_mismatch(u8 actual, u8 pattern, unsigned int index,
+ unsigned int counter, bool is_srcbuf)
+{
+ u8 diff = actual ^ pattern;
+ u8 expected = pattern | (~counter & PATTERN_COUNT_MASK);
+ const char *thread_name = current->comm;
+
+ if (is_srcbuf)
+ pr_warn("%s: srcbuf[0x%x] overwritten! Expected %02x, got %02x\n",
+ thread_name, index, expected, actual);
+ else if ((pattern & PATTERN_COPY)
+ && (diff & (PATTERN_COPY | PATTERN_OVERWRITE)))
+ pr_warn("%s: dstbuf[0x%x] not copied! Expected %02x, got %02x\n",
+ thread_name, index, expected, actual);
+ else if (diff & PATTERN_SRC)
+ pr_warn("%s: dstbuf[0x%x] was copied! Expected %02x, got %02x\n",
+ thread_name, index, expected, actual);
+ else
+ pr_warn("%s: dstbuf[0x%x] mismatch! Expected %02x, got %02x\n",
+ thread_name, index, expected, actual);
+}
+
+static unsigned int dmatest_verify(u8 **bufs, unsigned int start,
+ unsigned int end, unsigned int counter, u8 pattern,
+ bool is_srcbuf)
+{
+ unsigned int i;
+ unsigned int error_count = 0;
+ u8 actual;
+ u8 expected;
+ u8 *buf;
+ unsigned int counter_orig = counter;
+
+ for (; (buf = *bufs); bufs++) {
+ counter = counter_orig;
+ for (i = start; i < end; i++) {
+ actual = buf[i];
+ expected = pattern | (~counter & PATTERN_COUNT_MASK);
+ if (actual != expected) {
+ if (error_count < MAX_ERROR_COUNT)
+ dmatest_mismatch(actual, pattern, i,
+ counter, is_srcbuf);
+ error_count++;
+ }
+ counter++;
+ }
+ }
+
+ if (error_count > MAX_ERROR_COUNT)
+ pr_warn("%s: %u errors suppressed\n",
+ current->comm, error_count - MAX_ERROR_COUNT);
+
+ return error_count;
+}
+
+/* poor man's completion - we want to use wait_event_freezable() on it */
+struct dmatest_done {
+ bool done;
+ wait_queue_head_t *wait;
+};
+
+static void dmatest_callback(void *arg)
+{
+ struct dmatest_done *done = arg;
+
+ done->done = true;
+ wake_up_all(done->wait);
+}
+
+static unsigned int min_odd(unsigned int x, unsigned int y)
+{
+ unsigned int val = min(x, y);
+
+ return val % 2 ? val : val - 1;
+}
+
+static void result(const char *err, unsigned int n, unsigned int src_off,
+ unsigned int dst_off, unsigned int len, unsigned long data)
+{
+ pr_info("%s: result #%u: '%s' with src_off=0x%x dst_off=0x%x len=0x%x (%lu)\n",
+ current->comm, n, err, src_off, dst_off, len, data);
+}
+
+static void dbg_result(const char *err, unsigned int n, unsigned int src_off,
+ unsigned int dst_off, unsigned int len,
+ unsigned long data)
+{
+ pr_debug("%s: result #%u: '%s' with src_off=0x%x dst_off=0x%x len=0x%x (%lu)\n",
+ current->comm, n, err, src_off, dst_off, len, data);
+}
+
+#define verbose_result(err, n, src_off, dst_off, len, data) ({ \
+ if (verbose) \
+ result(err, n, src_off, dst_off, len, data); \
+ else \
+ dbg_result(err, n, src_off, dst_off, len, data); \
+})
+
+static unsigned long long dmatest_persec(s64 runtime, unsigned int val)
+{
+ unsigned long long per_sec = 1000000;
+
+ if (runtime <= 0)
+ return 0;
+
+ /* drop precision until runtime is 32-bits */
+ while (runtime > UINT_MAX) {
+ runtime >>= 1;
+ per_sec <<= 1;
+ }
+
+ per_sec *= val;
+ do_div(per_sec, runtime);
+ return per_sec;
+}
+
+static unsigned long long dmatest_KBs(s64 runtime, unsigned long long len)
+{
+ return dmatest_persec(runtime, len >> 10);
+}
+
+/*
+ * This function repeatedly tests DMA transfers of various lengths and
+ * offsets for a given operation type until it is told to exit by
+ * kthread_stop(). There may be multiple threads running this function
+ * in parallel for a single channel, and there may be multiple channels
+ * being tested in parallel.
+ *
+ * Before each test, the source and destination buffer is initialized
+ * with a known pattern. This pattern is different depending on
+ * whether it's in an area which is supposed to be copied or
+ * overwritten, and different in the source and destination buffers.
+ * So if the DMA engine doesn't copy exactly what we tell it to copy,
+ * we'll notice.
+ */
+static int dmatest_func(void *data)
+{
+ DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_wait);
+ struct dmatest_thread *thread = data;
+ struct dmatest_done done = { .wait = &done_wait };
+ struct dmatest_info *info;
+ struct dmatest_params *params;
+ struct dma_chan *chan;
+ struct dma_device *dev;
+ unsigned int src_off, dst_off, len;
+ unsigned int error_count;
+ unsigned int failed_tests = 0;
+ unsigned int total_tests = 0;
+ dma_cookie_t cookie;
+ enum dma_status status;
+ enum dma_ctrl_flags flags;
+ u8 *pq_coefs = NULL;
+ int ret;
+ int src_cnt;
+ int dst_cnt;
+ int i;
+ ktime_t ktime;
+ s64 runtime = 0;
+ unsigned long long total_len = 0;
+
+ set_freezable();
+
+ ret = -ENOMEM;
+
+ smp_rmb();
+ info = thread->info;
+ params = &info->params;
+ chan = thread->chan;
+ dev = chan->device;
+ if (thread->type == DMA_MEMCPY)
+ src_cnt = dst_cnt = 1;
+ else if (thread->type == DMA_XOR) {
+ /* force odd to ensure dst = src */
+ src_cnt = min_odd(params->xor_sources | 1, dev->max_xor);
+ dst_cnt = 1;
+ } else if (thread->type == DMA_PQ) {
+ /* force odd to ensure dst = src */
+ src_cnt = min_odd(params->pq_sources | 1, dma_maxpq(dev, 0));
+ dst_cnt = 2;
+
+ pq_coefs = kmalloc(params->pq_sources+1, GFP_KERNEL);
+ if (!pq_coefs)
+ goto err_thread_type;
+
+ for (i = 0; i < src_cnt; i++)
+ pq_coefs[i] = 1;
+ } else
+ goto err_thread_type;
+
+ thread->srcs = kcalloc(src_cnt+1, sizeof(u8 *), GFP_KERNEL);
+ if (!thread->srcs)
+ goto err_srcs;
+ for (i = 0; i < src_cnt; i++) {
+ thread->srcs[i] = kmalloc(params->buf_size, GFP_KERNEL);
+ if (!thread->srcs[i])
+ goto err_srcbuf;
+ }
+ thread->srcs[i] = NULL;
+
+ thread->dsts = kcalloc(dst_cnt+1, sizeof(u8 *), GFP_KERNEL);
+ if (!thread->dsts)
+ goto err_dsts;
+ for (i = 0; i < dst_cnt; i++) {
+ thread->dsts[i] = kmalloc(params->buf_size, GFP_KERNEL);
+ if (!thread->dsts[i])
+ goto err_dstbuf;
+ }
+ thread->dsts[i] = NULL;
+
+ set_user_nice(current, 10);
+
+ /*
+ * src and dst buffers are freed by ourselves below
+ */
+ flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
+
+ ktime = ktime_get();
+ while (!kthread_should_stop()
+ && !(params->iterations && total_tests >= params->iterations)) {
+ struct dma_async_tx_descriptor *tx = NULL;
+ struct dmaengine_unmap_data *um;
+ dma_addr_t srcs[src_cnt];
+ dma_addr_t *dsts;
+ u8 align = 0;
+
+ total_tests++;
+
+ /* honor alignment restrictions */
+ if (thread->type == DMA_MEMCPY)
+ align = dev->copy_align;
+ else if (thread->type == DMA_XOR)
+ align = dev->xor_align;
+ else if (thread->type == DMA_PQ)
+ align = dev->pq_align;
+
+ if (1 << align > params->buf_size) {
+ pr_err("%u-byte buffer too small for %d-byte alignment\n",
+ params->buf_size, 1 << align);
+ break;
+ }
+
+ if (params->noverify) {
+ len = params->buf_size;
+ src_off = 0;
+ dst_off = 0;
+ } else {
+ len = dmatest_random() % params->buf_size + 1;
+ len = (len >> align) << align;
+ if (!len)
+ len = 1 << align;
+ src_off = dmatest_random() % (params->buf_size - len + 1);
+ dst_off = dmatest_random() % (params->buf_size - len + 1);
+
+ src_off = (src_off >> align) << align;
+ dst_off = (dst_off >> align) << align;
+
+ dmatest_init_srcs(thread->srcs, src_off, len,
+ params->buf_size);
+ dmatest_init_dsts(thread->dsts, dst_off, len,
+ params->buf_size);
+ }
+
+ len = (len >> align) << align;
+ if (!len)
+ len = 1 << align;
+ total_len += len;
+
+ um = dmaengine_get_unmap_data(dev->dev, src_cnt+dst_cnt,
+ GFP_KERNEL);
+ if (!um) {
+ failed_tests++;
+ result("unmap data NULL", total_tests,
+ src_off, dst_off, len, ret);
+ continue;
+ }
+
+ um->len = params->buf_size;
+ for (i = 0; i < src_cnt; i++) {
+ void *buf = thread->srcs[i];
+ struct page *pg = virt_to_page(buf);
+ unsigned pg_off = (unsigned long) buf & ~PAGE_MASK;
+
+ um->addr[i] = dma_map_page(dev->dev, pg, pg_off,
+ um->len, DMA_TO_DEVICE);
+ srcs[i] = um->addr[i] + src_off;
+ ret = dma_mapping_error(dev->dev, um->addr[i]);
+ if (ret) {
+ dmaengine_unmap_put(um);
+ result("src mapping error", total_tests,
+ src_off, dst_off, len, ret);
+ failed_tests++;
+ continue;
+ }
+ um->to_cnt++;
+ }
+ /* map with DMA_BIDIRECTIONAL to force writeback/invalidate */
+ dsts = &um->addr[src_cnt];
+ for (i = 0; i < dst_cnt; i++) {
+ void *buf = thread->dsts[i];
+ struct page *pg = virt_to_page(buf);
+ unsigned pg_off = (unsigned long) buf & ~PAGE_MASK;
+
+ dsts[i] = dma_map_page(dev->dev, pg, pg_off, um->len,
+ DMA_BIDIRECTIONAL);
+ ret = dma_mapping_error(dev->dev, dsts[i]);
+ if (ret) {
+ dmaengine_unmap_put(um);
+ result("dst mapping error", total_tests,
+ src_off, dst_off, len, ret);
+ failed_tests++;
+ continue;
+ }
+ um->bidi_cnt++;
+ }
+
+ if (thread->type == DMA_MEMCPY)
+ tx = dev->device_prep_dma_memcpy(chan,
+ dsts[0] + dst_off,
+ srcs[0], len, flags);
+ else if (thread->type == DMA_XOR)
+ tx = dev->device_prep_dma_xor(chan,
+ dsts[0] + dst_off,
+ srcs, src_cnt,
+ len, flags);
+ else if (thread->type == DMA_PQ) {
+ dma_addr_t dma_pq[dst_cnt];
+
+ for (i = 0; i < dst_cnt; i++)
+ dma_pq[i] = dsts[i] + dst_off;
+ tx = dev->device_prep_dma_pq(chan, dma_pq, srcs,
+ src_cnt, pq_coefs,
+ len, flags);
+ }
+
+ if (!tx) {
+ dmaengine_unmap_put(um);
+ result("prep error", total_tests, src_off,
+ dst_off, len, ret);
+ msleep(100);
+ failed_tests++;
+ continue;
+ }
+
+ done.done = false;
+ tx->callback = dmatest_callback;
+ tx->callback_param = &done;
+ cookie = tx->tx_submit(tx);
+
+ if (dma_submit_error(cookie)) {
+ dmaengine_unmap_put(um);
+ result("submit error", total_tests, src_off,
+ dst_off, len, ret);
+ msleep(100);
+ failed_tests++;
+ continue;
+ }
+ dma_async_issue_pending(chan);
+
+ wait_event_freezable_timeout(done_wait, done.done,
+ msecs_to_jiffies(params->timeout));
+
+ status = dma_async_is_tx_complete(chan, cookie, NULL, NULL);
+
+ if (!done.done) {
+ /*
+ * We're leaving the timed out dma operation with
+ * dangling pointer to done_wait. To make this
+ * correct, we'll need to allocate wait_done for
+ * each test iteration and perform "who's gonna
+ * free it this time?" dancing. For now, just
+ * leave it dangling.
+ */
+ dmaengine_unmap_put(um);
+ result("test timed out", total_tests, src_off, dst_off,
+ len, 0);
+ failed_tests++;
+ continue;
+ } else if (status != DMA_COMPLETE) {
+ dmaengine_unmap_put(um);
+ result(status == DMA_ERROR ?
+ "completion error status" :
+ "completion busy status", total_tests, src_off,
+ dst_off, len, ret);
+ failed_tests++;
+ continue;
+ }
+
+ dmaengine_unmap_put(um);
+
+ if (params->noverify) {
+ verbose_result("test passed", total_tests, src_off,
+ dst_off, len, 0);
+ continue;
+ }
+
+ pr_debug("%s: verifying source buffer...\n", current->comm);
+ error_count = dmatest_verify(thread->srcs, 0, src_off,
+ 0, PATTERN_SRC, true);
+ error_count += dmatest_verify(thread->srcs, src_off,
+ src_off + len, src_off,
+ PATTERN_SRC | PATTERN_COPY, true);
+ error_count += dmatest_verify(thread->srcs, src_off + len,
+ params->buf_size, src_off + len,
+ PATTERN_SRC, true);
+
+ pr_debug("%s: verifying dest buffer...\n", current->comm);
+ error_count += dmatest_verify(thread->dsts, 0, dst_off,
+ 0, PATTERN_DST, false);
+ error_count += dmatest_verify(thread->dsts, dst_off,
+ dst_off + len, src_off,
+ PATTERN_SRC | PATTERN_COPY, false);
+ error_count += dmatest_verify(thread->dsts, dst_off + len,
+ params->buf_size, dst_off + len,
+ PATTERN_DST, false);
+
+ if (error_count) {
+ result("data error", total_tests, src_off, dst_off,
+ len, error_count);
+ failed_tests++;
+ } else {
+ verbose_result("test passed", total_tests, src_off,
+ dst_off, len, 0);
+ }
+ }
+ runtime = ktime_us_delta(ktime_get(), ktime);
+
+ ret = 0;
+ for (i = 0; thread->dsts[i]; i++)
+ kfree(thread->dsts[i]);
+err_dstbuf:
+ kfree(thread->dsts);
+err_dsts:
+ for (i = 0; thread->srcs[i]; i++)
+ kfree(thread->srcs[i]);
+err_srcbuf:
+ kfree(thread->srcs);
+err_srcs:
+ kfree(pq_coefs);
+err_thread_type:
+ pr_info("%s: summary %u tests, %u failures %llu iops %llu KB/s (%d)\n",
+ current->comm, total_tests, failed_tests,
+ dmatest_persec(runtime, total_tests),
+ dmatest_KBs(runtime, total_len), ret);
+
+ /* terminate all transfers on specified channels */
+ if (ret)
+ dmaengine_terminate_all(chan);
+
+ thread->done = true;
+ wake_up(&thread_wait);
+
+ return ret;
+}
+
+static void dmatest_cleanup_channel(struct dmatest_chan *dtc)
+{
+ struct dmatest_thread *thread;
+ struct dmatest_thread *_thread;
+ int ret;
+
+ list_for_each_entry_safe(thread, _thread, &dtc->threads, node) {
+ ret = kthread_stop(thread->task);
+ pr_debug("thread %s exited with status %d\n",
+ thread->task->comm, ret);
+ list_del(&thread->node);
+ put_task_struct(thread->task);
+ kfree(thread);
+ }
+
+ /* terminate all transfers on specified channels */
+ dmaengine_terminate_all(dtc->chan);
+
+ kfree(dtc);
+}
+
+static int dmatest_add_threads(struct dmatest_info *info,
+ struct dmatest_chan *dtc, enum dma_transaction_type type)
+{
+ struct dmatest_params *params = &info->params;
+ struct dmatest_thread *thread;
+ struct dma_chan *chan = dtc->chan;
+ char *op;
+ unsigned int i;
+
+ if (type == DMA_MEMCPY)
+ op = "copy";
+ else if (type == DMA_XOR)
+ op = "xor";
+ else if (type == DMA_PQ)
+ op = "pq";
+ else
+ return -EINVAL;
+
+ for (i = 0; i < params->threads_per_chan; i++) {
+ thread = kzalloc(sizeof(struct dmatest_thread), GFP_KERNEL);
+ if (!thread) {
+ pr_warn("No memory for %s-%s%u\n",
+ dma_chan_name(chan), op, i);
+ break;
+ }
+ thread->info = info;
+ thread->chan = dtc->chan;
+ thread->type = type;
+ smp_wmb();
+ thread->task = kthread_create(dmatest_func, thread, "%s-%s%u",
+ dma_chan_name(chan), op, i);
+ if (IS_ERR(thread->task)) {
+ pr_warn("Failed to create thread %s-%s%u\n",
+ dma_chan_name(chan), op, i);
+ kfree(thread);
+ break;
+ }
+
+ /* srcbuf and dstbuf are allocated by the thread itself */
+ get_task_struct(thread->task);
+ list_add_tail(&thread->node, &dtc->threads);
+ wake_up_process(thread->task);
+ }
+
+ return i;
+}
+
+static int dmatest_add_channel(struct dmatest_info *info,
+ struct dma_chan *chan)
+{
+ struct dmatest_chan *dtc;
+ struct dma_device *dma_dev = chan->device;
+ unsigned int thread_count = 0;
+ int cnt;
+
+ dtc = kmalloc(sizeof(struct dmatest_chan), GFP_KERNEL);
+ if (!dtc) {
+ pr_warn("No memory for %s\n", dma_chan_name(chan));
+ return -ENOMEM;
+ }
+
+ dtc->chan = chan;
+ INIT_LIST_HEAD(&dtc->threads);
+
+ if (dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask)) {
+ cnt = dmatest_add_threads(info, dtc, DMA_MEMCPY);
+ thread_count += cnt > 0 ? cnt : 0;
+ }
+ if (dma_has_cap(DMA_XOR, dma_dev->cap_mask)) {
+ cnt = dmatest_add_threads(info, dtc, DMA_XOR);
+ thread_count += cnt > 0 ? cnt : 0;
+ }
+ if (dma_has_cap(DMA_PQ, dma_dev->cap_mask)) {
+ cnt = dmatest_add_threads(info, dtc, DMA_PQ);
+ thread_count += cnt > 0 ? cnt : 0;
+ }
+
+ pr_info("Started %u threads using %s\n",
+ thread_count, dma_chan_name(chan));
+
+ list_add_tail(&dtc->node, &info->channels);
+ info->nr_channels++;
+
+ return 0;
+}
+
+static bool filter(struct dma_chan *chan, void *param)
+{
+ struct dmatest_params *params = param;
+
+ if (!dmatest_match_channel(params, chan) ||
+ !dmatest_match_device(params, chan->device))
+ return false;
+ else
+ return true;
+}
+
+static void request_channels(struct dmatest_info *info,
+ enum dma_transaction_type type)
+{
+ dma_cap_mask_t mask;
+
+ dma_cap_zero(mask);
+ dma_cap_set(type, mask);
+ for (;;) {
+ struct dmatest_params *params = &info->params;
+ struct dma_chan *chan;
+
+ chan = dma_request_channel(mask, filter, params);
+ if (chan) {
+ if (dmatest_add_channel(info, chan)) {
+ dma_release_channel(chan);
+ break; /* add_channel failed, punt */
+ }
+ } else
+ break; /* no more channels available */
+ if (params->max_channels &&
+ info->nr_channels >= params->max_channels)
+ break; /* we have all we need */
+ }
+}
+
+static void run_threaded_test(struct dmatest_info *info)
+{
+ struct dmatest_params *params = &info->params;
+
+ /* Copy test parameters */
+ params->buf_size = test_buf_size;
+ strlcpy(params->channel, strim(test_channel), sizeof(params->channel));
+ strlcpy(params->device, strim(test_device), sizeof(params->device));
+ params->threads_per_chan = threads_per_chan;
+ params->max_channels = max_channels;
+ params->iterations = iterations;
+ params->xor_sources = xor_sources;
+ params->pq_sources = pq_sources;
+ params->timeout = timeout;
+ params->noverify = noverify;
+
+ request_channels(info, DMA_MEMCPY);
+ request_channels(info, DMA_XOR);
+ request_channels(info, DMA_PQ);
+}
+
+static void stop_threaded_test(struct dmatest_info *info)
+{
+ struct dmatest_chan *dtc, *_dtc;
+ struct dma_chan *chan;
+
+ list_for_each_entry_safe(dtc, _dtc, &info->channels, node) {
+ list_del(&dtc->node);
+ chan = dtc->chan;
+ dmatest_cleanup_channel(dtc);
+ pr_debug("dropped channel %s\n", dma_chan_name(chan));
+ dma_release_channel(chan);
+ }
+
+ info->nr_channels = 0;
+}
+
+static void restart_threaded_test(struct dmatest_info *info, bool run)
+{
+ /* we might be called early to set run=, defer running until all
+ * parameters have been evaluated
+ */
+ if (!info->did_init)
+ return;
+
+ /* Stop any running test first */
+ stop_threaded_test(info);
+
+ /* Run test with new parameters */
+ run_threaded_test(info);
+}
+
+static int dmatest_run_get(char *val, const struct kernel_param *kp)
+{
+ struct dmatest_info *info = &test_info;
+
+ mutex_lock(&info->lock);
+ if (is_threaded_test_run(info)) {
+ dmatest_run = true;
+ } else {
+ stop_threaded_test(info);
+ dmatest_run = false;
+ }
+ mutex_unlock(&info->lock);
+
+ return param_get_bool(val, kp);
+}
+
+static int dmatest_run_set(const char *val, const struct kernel_param *kp)
+{
+ struct dmatest_info *info = &test_info;
+ int ret;
+
+ mutex_lock(&info->lock);
+ ret = param_set_bool(val, kp);
+ if (ret) {
+ mutex_unlock(&info->lock);
+ return ret;
+ }
+
+ if (is_threaded_test_run(info))
+ ret = -EBUSY;
+ else if (dmatest_run)
+ restart_threaded_test(info, dmatest_run);
+
+ mutex_unlock(&info->lock);
+
+ return ret;
+}
+
+static int __init dmatest_init(void)
+{
+ struct dmatest_info *info = &test_info;
+ struct dmatest_params *params = &info->params;
+
+ if (dmatest_run) {
+ mutex_lock(&info->lock);
+ run_threaded_test(info);
+ mutex_unlock(&info->lock);
+ }
+
+ if (params->iterations && wait)
+ wait_event(thread_wait, !is_threaded_test_run(info));
+
+ /* module parameters are stable, inittime tests are started,
+ * let userspace take over 'run' control
+ */
+ info->did_init = true;
+
+ return 0;
+}
+/* when compiled-in wait for drivers to load first */
+late_initcall(dmatest_init);
+
+static void __exit dmatest_exit(void)
+{
+ struct dmatest_info *info = &test_info;
+
+ mutex_lock(&info->lock);
+ stop_threaded_test(info);
+ mutex_unlock(&info->lock);
+}
+module_exit(dmatest_exit);
+
+MODULE_AUTHOR("Haavard Skinnemoen (Atmel)");
+MODULE_LICENSE("GPL v2");
ef='/linux/diff/arch/sparc/include/asm/io_64.h?id2=966812dc98e6a7fcdf759cbfa0efab77500a8868'>arch/sparc/include/asm/io_64.h542
-rw-r--r--arch/sparc/include/asm/ioctls.h13
-rw-r--r--arch/sparc/include/asm/iommu.h8
-rw-r--r--arch/sparc/include/asm/iommu_32.h121
-rw-r--r--arch/sparc/include/asm/iommu_64.h65
-rw-r--r--arch/sparc/include/asm/irq.h8
-rw-r--r--arch/sparc/include/asm/irq_32.h24
-rw-r--r--arch/sparc/include/asm/irq_64.h101
-rw-r--r--arch/sparc/include/asm/irqflags.h8
-rw-r--r--arch/sparc/include/asm/irqflags_32.h47
-rw-r--r--arch/sparc/include/asm/irqflags_64.h97
-rw-r--r--arch/sparc/include/asm/jump_label.h35
-rw-r--r--arch/sparc/include/asm/kdebug.h8
-rw-r--r--arch/sparc/include/asm/kdebug_32.h74
-rw-r--r--arch/sparc/include/asm/kdebug_64.h21
-rw-r--r--arch/sparc/include/asm/kgdb.h41
-rw-r--r--arch/sparc/include/asm/kmap_types.h10
-rw-r--r--arch/sparc/include/asm/kprobes.h51
-rw-r--r--arch/sparc/include/asm/ldc.h138
-rw-r--r--arch/sparc/include/asm/leon.h257
-rw-r--r--arch/sparc/include/asm/leon_amba.h266
-rw-r--r--arch/sparc/include/asm/leon_pci.h22
-rw-r--r--arch/sparc/include/asm/lsu.h19
-rw-r--r--arch/sparc/include/asm/machines.h50
-rw-r--r--arch/sparc/include/asm/mbus.h96
-rw-r--r--arch/sparc/include/asm/mc146818rtc.h13
-rw-r--r--arch/sparc/include/asm/mc146818rtc_32.h29
-rw-r--r--arch/sparc/include/asm/mc146818rtc_64.h28
-rw-r--r--arch/sparc/include/asm/mdesc.h80
-rw-r--r--arch/sparc/include/asm/memctrl.h9
-rw-r--r--arch/sparc/include/asm/mman.h10
-rw-r--r--arch/sparc/include/asm/mmu.h8
-rw-r--r--arch/sparc/include/asm/mmu_32.h10
-rw-r--r--arch/sparc/include/asm/mmu_64.h109
-rw-r--r--arch/sparc/include/asm/mmu_context.h8
-rw-r--r--arch/sparc/include/asm/mmu_context_32.h35
-rw-r--r--arch/sparc/include/asm/mmu_context_64.h156
-rw-r--r--arch/sparc/include/asm/mmzone.h17
-rw-r--r--arch/sparc/include/asm/msi.h31
-rw-r--r--arch/sparc/include/asm/mxcc.h137
-rw-r--r--arch/sparc/include/asm/nmi.h13
-rw-r--r--arch/sparc/include/asm/ns87303.h117
-rw-r--r--arch/sparc/include/asm/obio.h225
-rw-r--r--arch/sparc/include/asm/openprom.h279
-rw-r--r--arch/sparc/include/asm/oplib.h8
-rw-r--r--arch/sparc/include/asm/oplib_32.h183
-rw-r--r--arch/sparc/include/asm/oplib_64.h250
-rw-r--r--arch/sparc/include/asm/page.h11
-rw-r--r--arch/sparc/include/asm/page_32.h141
-rw-r--r--arch/sparc/include/asm/page_64.h159
-rw-r--r--arch/sparc/include/asm/parport.h253
-rw-r--r--arch/sparc/include/asm/pbm.h47
-rw-r--r--arch/sparc/include/asm/pci.h11
-rw-r--r--arch/sparc/include/asm/pci_32.h56
-rw-r--r--arch/sparc/include/asm/pci_64.h82
-rw-r--r--arch/sparc/include/asm/pcic.h129
-rw-r--r--arch/sparc/include/asm/pcr.h50
-rw-r--r--arch/sparc/include/asm/percpu.h8
-rw-r--r--arch/sparc/include/asm/percpu_32.h6
-rw-r--r--arch/sparc/include/asm/percpu_64.h24
-rw-r--r--arch/sparc/include/asm/perf_event.h29
-rw-r--r--arch/sparc/include/asm/pgalloc.h8
-rw-r--r--arch/sparc/include/asm/pgalloc_32.h79
-rw-r--r--arch/sparc/include/asm/pgalloc_64.h94
-rw-r--r--arch/sparc/include/asm/pgtable.h8
-rw-r--r--arch/sparc/include/asm/pgtable_32.h475
-rw-r--r--arch/sparc/include/asm/pgtable_64.h1001
-rw-r--r--arch/sparc/include/asm/pgtsrmmu.h182
-rw-r--r--arch/sparc/include/asm/pil.h31
-rw-r--r--arch/sparc/include/asm/processor.h11
-rw-r--r--arch/sparc/include/asm/processor_32.h126
-rw-r--r--arch/sparc/include/asm/processor_64.h260
-rw-r--r--arch/sparc/include/asm/prom.h63
-rw-r--r--arch/sparc/include/asm/psr.h67
-rw-r--r--arch/sparc/include/asm/ptrace.h126
-rw-r--r--arch/sparc/include/asm/ross.h191
-rw-r--r--arch/sparc/include/asm/rwsem.h124
-rw-r--r--arch/sparc/include/asm/sbi.h115
-rw-r--r--arch/sparc/include/asm/scatterlist.h8
-rw-r--r--arch/sparc/include/asm/scratchpad.h14
-rw-r--r--arch/sparc/include/asm/seccomp.h15
-rw-r--r--arch/sparc/include/asm/sections.h13
-rw-r--r--arch/sparc/include/asm/setup.h66
-rw-r--r--arch/sparc/include/asm/sfafsr.h82
-rw-r--r--arch/sparc/include/asm/sfp-machine.h8
-rw-r--r--arch/sparc/include/asm/sfp-machine_32.h212
-rw-r--r--arch/sparc/include/asm/sfp-machine_64.h93
-rw-r--r--arch/sparc/include/asm/shmparam.h8
-rw-r--r--arch/sparc/include/asm/shmparam_32.h9
-rw-r--r--arch/sparc/include/asm/shmparam_64.h10
-rw-r--r--arch/sparc/include/asm/sigcontext.h108
-rw-r--r--arch/sparc/include/asm/siginfo.h13
-rw-r--r--arch/sparc/include/asm/signal.h28
-rw-r--r--arch/sparc/include/asm/smp.h8
-rw-r--r--arch/sparc/include/asm/smp_32.h132
-rw-r--r--arch/sparc/include/asm/smp_64.h78
-rw-r--r--arch/sparc/include/asm/sparsemem.h14
-rw-r--r--arch/sparc/include/asm/spinlock.h8
-rw-r--r--arch/sparc/include/asm/spinlock_32.h200
-rw-r--r--arch/sparc/include/asm/spinlock_64.h225
-rw-r--r--arch/sparc/include/asm/spinlock_types.h20
-rw-r--r--arch/sparc/include/asm/spitfire.h348
-rw-r--r--arch/sparc/include/asm/stacktrace.h6
-rw-r--r--arch/sparc/include/asm/starfire.h20
-rw-r--r--arch/sparc/include/asm/string.h8
-rw-r--r--arch/sparc/include/asm/string_32.h70
-rw-r--r--arch/sparc/include/asm/string_64.h62
-rw-r--r--arch/sparc/include/asm/sunbpp.h80
-rw-r--r--arch/sparc/include/asm/swift.h106
-rw-r--r--arch/sparc/include/asm/switch_to.h8
-rw-r--r--arch/sparc/include/asm/switch_to_32.h106
-rw-r--r--arch/sparc/include/asm/switch_to_64.h71
-rw-r--r--arch/sparc/include/asm/syscall.h127
-rw-r--r--arch/sparc/include/asm/syscalls.h11
-rw-r--r--arch/sparc/include/asm/termbits.h8
-rw-r--r--arch/sparc/include/asm/termios.h146
-rw-r--r--arch/sparc/include/asm/thread_info.h8
-rw-r--r--arch/sparc/include/asm/thread_info_32.h135
-rw-r--r--arch/sparc/include/asm/thread_info_64.h267
-rw-r--r--arch/sparc/include/asm/timer.h8
-rw-r--r--arch/sparc/include/asm/timer_32.h44
-rw-r--r--arch/sparc/include/asm/timer_64.h30
-rw-r--r--arch/sparc/include/asm/timex.h8
-rw-r--r--arch/sparc/include/asm/timex_32.h15
-rw-r--r--arch/sparc/include/asm/timex_64.h19
-rw-r--r--arch/sparc/include/asm/tlb.h8
-rw-r--r--arch/sparc/include/asm/tlb_32.h24
-rw-r--r--arch/sparc/include/asm/tlb_64.h32
-rw-r--r--arch/sparc/include/asm/tlbflush.h8
-rw-r--r--arch/sparc/include/asm/tlbflush_32.h24
-rw-r--r--arch/sparc/include/asm/tlbflush_64.h76
-rw-r--r--arch/sparc/include/asm/topology.h8
-rw-r--r--arch/sparc/include/asm/topology_32.h6
-rw-r--r--arch/sparc/include/asm/topology_64.h53
-rw-r--r--arch/sparc/include/asm/trap_block.h207
-rw-r--r--arch/sparc/include/asm/traps.h24
-rw-r--r--arch/sparc/include/asm/tsb.h304
-rw-r--r--arch/sparc/include/asm/tsunami.h64
-rw-r--r--arch/sparc/include/asm/ttable.h677
-rw-r--r--arch/sparc/include/asm/turbosparc.h125
-rw-r--r--arch/sparc/include/asm/uaccess.h14
-rw-r--r--arch/sparc/include/asm/uaccess_32.h314
-rw-r--r--arch/sparc/include/asm/uaccess_64.h275
-rw-r--r--arch/sparc/include/asm/unaligned.h10
-rw-r--r--arch/sparc/include/asm/unistd.h47
-rw-r--r--arch/sparc/include/asm/upa.h109
-rw-r--r--arch/sparc/include/asm/user.h6
-rw-r--r--arch/sparc/include/asm/vaddrs.h70
-rw-r--r--arch/sparc/include/asm/vga.h34
-rw-r--r--arch/sparc/include/asm/viking.h253
-rw-r--r--arch/sparc/include/asm/vio.h411
-rw-r--r--arch/sparc/include/asm/visasm.h64
-rw-r--r--arch/sparc/include/asm/winmacro.h131
-rw-r--r--arch/sparc/include/asm/xor.h8
-rw-r--r--arch/sparc/include/asm/xor_32.h269
-rw-r--r--arch/sparc/include/asm/xor_64.h73
-rw-r--r--arch/sparc/include/uapi/asm/Kbuild50
-rw-r--r--arch/sparc/include/uapi/asm/apc.h64
-rw-r--r--arch/sparc/include/uapi/asm/asi.h297
-rw-r--r--arch/sparc/include/uapi/asm/auxvec.h4
-rw-r--r--arch/sparc/include/uapi/asm/bitsperlong.h13
-rw-r--r--arch/sparc/include/uapi/asm/byteorder.h6
-rw-r--r--arch/sparc/include/uapi/asm/display7seg.h79
-rw-r--r--arch/sparc/include/uapi/asm/envctrl.h103
-rw-r--r--arch/sparc/include/uapi/asm/errno.h117
-rw-r--r--arch/sparc/include/uapi/asm/fbio.h259
-rw-r--r--arch/sparc/include/uapi/asm/fcntl.h56
-rw-r--r--arch/sparc/include/uapi/asm/ioctl.h67
-rw-r--r--arch/sparc/include/uapi/asm/ioctls.h134
-rw-r--r--arch/sparc/include/uapi/asm/ipcbuf.h32
-rw-r--r--arch/sparc/include/uapi/asm/jsflash.h39
-rw-r--r--arch/sparc/include/uapi/asm/kvm_para.h1
-rw-r--r--arch/sparc/include/uapi/asm/mman.h27
-rw-r--r--arch/sparc/include/uapi/asm/msgbuf.h38
-rw-r--r--arch/sparc/include/uapi/asm/openpromio.h69
-rw-r--r--arch/sparc/include/uapi/asm/param.h7
-rw-r--r--arch/sparc/include/uapi/asm/perfctr.h166
-rw-r--r--arch/sparc/include/uapi/asm/poll.h12
-rw-r--r--arch/sparc/include/uapi/asm/posix_types.h49
-rw-r--r--arch/sparc/include/uapi/asm/psr.h47
-rw-r--r--arch/sparc/include/uapi/asm/psrcompat.h45
-rw-r--r--arch/sparc/include/uapi/asm/pstate.h105
-rw-r--r--arch/sparc/include/uapi/asm/ptrace.h352
-rw-r--r--arch/sparc/include/uapi/asm/resource.h30
-rw-r--r--arch/sparc/include/uapi/asm/sembuf.h31
-rw-r--r--arch/sparc/include/uapi/asm/setup.h15
-rw-r--r--arch/sparc/include/uapi/asm/shmbuf.h50
-rw-r--r--arch/sparc/include/uapi/asm/sigcontext.h4
-rw-r--r--arch/sparc/include/uapi/asm/siginfo.h25
-rw-r--r--arch/sparc/include/uapi/asm/signal.h181
-rw-r--r--arch/sparc/include/uapi/asm/socket.h84
-rw-r--r--arch/sparc/include/uapi/asm/sockios.h14
-rw-r--r--arch/sparc/include/uapi/asm/stat.h107
-rw-r--r--arch/sparc/include/uapi/asm/statfs.h6
-rw-r--r--arch/sparc/include/uapi/asm/swab.h45
-rw-r--r--arch/sparc/include/uapi/asm/termbits.h263
-rw-r--r--arch/sparc/include/uapi/asm/termios.h43
-rw-r--r--arch/sparc/include/uapi/asm/traps.h120
-rw-r--r--arch/sparc/include/uapi/asm/uctx.h71
-rw-r--r--arch/sparc/include/uapi/asm/unistd.h431
-rw-r--r--arch/sparc/include/uapi/asm/utrap.h51
-rw-r--r--arch/sparc/include/uapi/asm/watchdog.h31
-rw-r--r--arch/sparc/kernel/.gitignore1
-rw-r--r--arch/sparc/kernel/Makefile132
-rw-r--r--arch/sparc/kernel/apc.c102
-rw-r--r--arch/sparc/kernel/asm-offsets.c50
-rw-r--r--arch/sparc/kernel/audit.c79
-rw-r--r--arch/sparc/kernel/auxio_32.c (renamed from arch/sparc/kernel/auxio.c)42
-rw-r--r--arch/sparc/kernel/auxio_64.c152
-rw-r--r--arch/sparc/kernel/btext.c672
-rw-r--r--arch/sparc/kernel/central.c272
-rw-r--r--arch/sparc/kernel/cherrs.S579
-rw-r--r--arch/sparc/kernel/chmc.c864
-rw-r--r--arch/sparc/kernel/compat_audit.c44
-rw-r--r--arch/sparc/kernel/cpu.c608
-rw-r--r--arch/sparc/kernel/cpumap.c435
-rw-r--r--arch/sparc/kernel/cpumap.h16
-rw-r--r--arch/sparc/kernel/devices.c55
-rw-r--r--arch/sparc/kernel/dma.c12
-rw-r--r--arch/sparc/kernel/ds.c1273
-rw-r--r--arch/sparc/kernel/dtlb_miss.S39
-rw-r--r--arch/sparc/kernel/dtlb_prot.S54
-rw-r--r--arch/sparc/kernel/ebus.c544
-rw-r--r--arch/sparc/kernel/entry.S1018
-rw-r--r--arch/sparc/kernel/entry.h254
-rw-r--r--arch/sparc/kernel/errtbls.c276
-rw-r--r--arch/sparc/kernel/etrap_32.S (renamed from arch/sparc/kernel/etrap.S)71
-rw-r--r--arch/sparc/kernel/etrap_64.S240
-rw-r--r--arch/sparc/kernel/fpu_traps.S384
-rw-r--r--arch/sparc/kernel/ftrace.c147
-rw-r--r--arch/sparc/kernel/getsetcc.S24
-rw-r--r--arch/sparc/kernel/head.S1325
-rw-r--r--arch/sparc/kernel/head_32.S815
-rw-r--r--arch/sparc/kernel/head_64.S984
-rw-r--r--arch/sparc/kernel/helpers.S63
-rw-r--r--arch/sparc/kernel/hvapi.c200
-rw-r--r--arch/sparc/kernel/hvcalls.S823
-rw-r--r--arch/sparc/kernel/hvtramp.S137
-rw-r--r--arch/sparc/kernel/idprom.c76
-rw-r--r--arch/sparc/kernel/init_task.c28
-rw-r--r--arch/sparc/kernel/iommu.c862
-rw-r--r--arch/sparc/kernel/iommu_common.h59
-rw-r--r--arch/sparc/kernel/ioport.c597
-rw-r--r--arch/sparc/kernel/irq.c621
-rw-r--r--arch/sparc/kernel/irq.h101
-rw-r--r--arch/sparc/kernel/irq_32.c362
-rw-r--r--arch/sparc/kernel/irq_64.c973
-rw-r--r--arch/sparc/kernel/itlb_miss.S39
-rw-r--r--arch/sparc/kernel/ivec.S51
-rw-r--r--arch/sparc/kernel/jump_label.c41
-rw-r--r--arch/sparc/kernel/kernel.h186
-rw-r--r--arch/sparc/kernel/kgdb_32.c172
-rw-r--r--arch/sparc/kernel/kgdb_64.c200
-rw-r--r--arch/sparc/kernel/kprobes.c603
-rw-r--r--arch/sparc/kernel/kstack.h83
-rw-r--r--arch/sparc/kernel/ktlb.S352
-rw-r--r--arch/sparc/kernel/ldc.c2374
-rw-r--r--arch/sparc/kernel/led.c39
-rw-r--r--arch/sparc/kernel/leon_kernel.c499
-rw-r--r--arch/sparc/kernel/leon_pci.c100
-rw-r--r--arch/sparc/kernel/leon_pci_grpci1.c722
-rw-r--r--arch/sparc/kernel/leon_pci_grpci2.c914
-rw-r--r--arch/sparc/kernel/leon_pmc.c93
-rw-r--r--arch/sparc/kernel/leon_smp.c469
-rw-r--r--arch/sparc/kernel/mdesc.c974
-rw-r--r--arch/sparc/kernel/misctrap.S97
-rw-r--r--arch/sparc/kernel/module.c176
-rw-r--r--arch/sparc/kernel/muldiv.c240
-rw-r--r--arch/sparc/kernel/nmi.c273
-rw-r--r--arch/sparc/kernel/of_device.c821
-rw-r--r--arch/sparc/kernel/of_device_32.c429
-rw-r--r--arch/sparc/kernel/of_device_64.c726
-rw-r--r--arch/sparc/kernel/of_device_common.c178
-rw-r--r--arch/sparc/kernel/of_device_common.h36
-rw-r--r--arch/sparc/kernel/pci.c1009
-rw-r--r--arch/sparc/kernel/pci_common.c553
-rw-r--r--arch/sparc/kernel/pci_fire.c522
-rw-r--r--arch/sparc/kernel/pci_impl.h186
-rw-r--r--arch/sparc/kernel/pci_msi.c446
-rw-r--r--arch/sparc/kernel/pci_psycho.c618
-rw-r--r--arch/sparc/kernel/pci_sabre.c614
-rw-r--r--arch/sparc/kernel/pci_schizo.c1509
-rw-r--r--arch/sparc/kernel/pci_sun4v.c1024
-rw-r--r--arch/sparc/kernel/pci_sun4v.h92
-rw-r--r--arch/sparc/kernel/pci_sun4v_asm.S362
-rw-r--r--arch/sparc/kernel/pcic.c379
-rw-r--r--arch/sparc/kernel/pcr.c300
-rw-r--r--arch/sparc/kernel/perf_event.c1804
-rw-r--r--arch/sparc/kernel/pmc.c79
-rw-r--r--arch/sparc/kernel/power.c76
-rw-r--r--arch/sparc/kernel/process.c745
-rw-r--r--arch/sparc/kernel/process_32.c495
-rw-r--r--arch/sparc/kernel/process_64.c772
-rw-r--r--arch/sparc/kernel/prom.c583
-rw-r--r--arch/sparc/kernel/prom.h11
-rw-r--r--arch/sparc/kernel/prom_32.c337
-rw-r--r--arch/sparc/kernel/prom_64.c635
-rw-r--r--arch/sparc/kernel/prom_common.c162
-rw-r--r--arch/sparc/kernel/prom_irqtrans.c842
-rw-r--r--arch/sparc/kernel/psycho_common.c470
-rw-r--r--arch/sparc/kernel/psycho_common.h48
-rw-r--r--arch/sparc/kernel/ptrace.c601
-rw-r--r--arch/sparc/kernel/ptrace_32.c458
-rw-r--r--arch/sparc/kernel/ptrace_64.c1106
-rw-r--r--arch/sparc/kernel/reboot.c53
-rw-r--r--arch/sparc/kernel/rtrap_32.S (renamed from arch/sparc/kernel/rtrap.S)120
-rw-r--r--arch/sparc/kernel/rtrap_64.S371
-rw-r--r--arch/sparc/kernel/sbus.c676
-rw-r--r--arch/sparc/kernel/sclow.S86
-rw-r--r--arch/sparc/kernel/semaphore.c155
-rw-r--r--arch/sparc/kernel/setup_32.c (renamed from arch/sparc/kernel/setup.c)333
-rw-r--r--arch/sparc/kernel/setup_64.c635
-rw-r--r--arch/sparc/kernel/signal.c1124
-rw-r--r--arch/sparc/kernel/signal32.c794
-rw-r--r--arch/sparc/kernel/signal_32.c556
-rw-r--r--arch/sparc/kernel/signal_64.c547
-rw-r--r--arch/sparc/kernel/sigutil.h9
-rw-r--r--arch/sparc/kernel/sigutil_32.c121
-rw-r--r--arch/sparc/kernel/sigutil_64.c95
-rw-r--r--arch/sparc/kernel/smp.c439
-rw-r--r--arch/sparc/kernel/smp_32.c398
-rw-r--r--arch/sparc/kernel/smp_64.c1523
-rw-r--r--arch/sparc/kernel/sparc-stub.c724
-rw-r--r--arch/sparc/kernel/sparc_ksyms.c300
-rw-r--r--arch/sparc/kernel/sparc_ksyms_32.c31
-rw-r--r--arch/sparc/kernel/sparc_ksyms_64.c52
-rw-r--r--arch/sparc/kernel/spiterrs.S245
-rw-r--r--arch/sparc/kernel/sstate.c122
-rw-r--r--arch/sparc/kernel/stacktrace.c85
-rw-r--r--arch/sparc/kernel/starfire.c116
-rw-r--r--arch/sparc/kernel/sun4c_irq.c246
-rw-r--r--arch/sparc/kernel/sun4d_irq.c860
-rw-r--r--arch/sparc/kernel/sun4d_smp.c467
-rw-r--r--arch/sparc/kernel/sun4m_irq.c665
-rw-r--r--arch/sparc/kernel/sun4m_smp.c326
-rw-r--r--arch/sparc/kernel/sun4setup.c75
-rw-r--r--arch/sparc/kernel/sun4v_ivec.S341
-rw-r--r--arch/sparc/kernel/sun4v_tlb_miss.S428
-rw-r--r--arch/sparc/kernel/sunos_asm.S67
-rw-r--r--arch/sparc/kernel/sunos_ioctl.c231
-rw-r--r--arch/sparc/kernel/sys32.S278
-rw-r--r--arch/sparc/kernel/sys_solaris.c36
-rw-r--r--arch/sparc/kernel/sys_sparc.c513
-rw-r--r--arch/sparc/kernel/sys_sparc32.c256
-rw-r--r--arch/sparc/kernel/sys_sparc_32.c223
-rw-r--r--arch/sparc/kernel/sys_sparc_64.c647
-rw-r--r--arch/sparc/kernel/sys_sunos.c1210
-rw-r--r--arch/sparc/kernel/syscalls.S260
-rw-r--r--arch/sparc/kernel/sysfs.c320
-rw-r--r--arch/sparc/kernel/systbls.S200
-rw-r--r--arch/sparc/kernel/systbls.h103
-rw-r--r--arch/sparc/kernel/systbls_32.S89
-rw-r--r--arch/sparc/kernel/systbls_64.S169
-rw-r--r--arch/sparc/kernel/tadpole.c126
-rw-r--r--arch/sparc/kernel/tick14.c84
-rw-r--r--arch/sparc/kernel/time.c592
-rw-r--r--arch/sparc/kernel/time_32.c382
-rw-r--r--arch/sparc/kernel/time_64.c850
-rw-r--r--arch/sparc/kernel/trampoline_32.S (renamed from arch/sparc/kernel/trampoline.S)90
-rw-r--r--arch/sparc/kernel/trampoline_64.S411
-rw-r--r--arch/sparc/kernel/traps_32.c (renamed from arch/sparc/kernel/traps.c)86
-rw-r--r--arch/sparc/kernel/traps_64.c2796
-rw-r--r--arch/sparc/kernel/tsb.S582
-rw-r--r--arch/sparc/kernel/ttable_32.S417
-rw-r--r--arch/sparc/kernel/ttable_64.S272
-rw-r--r--arch/sparc/kernel/una_asm_32.S153
-rw-r--r--arch/sparc/kernel/una_asm_64.S146
-rw-r--r--arch/sparc/kernel/unaligned_32.c (renamed from arch/sparc/kernel/unaligned.c)289
-rw-r--r--arch/sparc/kernel/unaligned_64.c700
-rw-r--r--arch/sparc/kernel/utrap.S29
-rw-r--r--arch/sparc/kernel/vio.c463
-rw-r--r--arch/sparc/kernel/viohs.c824
-rw-r--r--arch/sparc/kernel/visemul.c898
-rw-r--r--arch/sparc/kernel/vmlinux.lds.S226
-rw-r--r--arch/sparc/kernel/windows.c12
-rw-r--r--arch/sparc/kernel/winfixup.S158
-rw-r--r--arch/sparc/kernel/wof.S93
-rw-r--r--arch/sparc/kernel/wuf.S90
-rw-r--r--arch/sparc/lib/GENbzero.S156
-rw-r--r--arch/sparc/lib/GENcopy_from_user.S30
-rw-r--r--arch/sparc/lib/GENcopy_to_user.S34
-rw-r--r--arch/sparc/lib/GENmemcpy.S121
-rw-r--r--arch/sparc/lib/GENpage.S77
-rw-r--r--arch/sparc/lib/GENpatch.S33
-rw-r--r--arch/sparc/lib/Makefile50
-rw-r--r--arch/sparc/lib/NG2copy_from_user.S35
-rw-r--r--arch/sparc/lib/NG2copy_to_user.S44
-rw-r--r--arch/sparc/lib/NG2memcpy.S521
-rw-r--r--arch/sparc/lib/NG2patch.S33
-rw-r--r--arch/sparc/lib/NG4clear_page.S29
-rw-r--r--arch/sparc/lib/NG4copy_from_user.S30
-rw-r--r--arch/sparc/lib/NG4copy_page.S57
-rw-r--r--arch/sparc/lib/NG4copy_to_user.S39
-rw-r--r--arch/sparc/lib/NG4memcpy.S360
-rw-r--r--arch/sparc/lib/NG4memset.S105
-rw-r--r--arch/sparc/lib/NG4patch.S54
-rw-r--r--arch/sparc/lib/NGbzero.S160
-rw-r--r--arch/sparc/lib/NGcopy_from_user.S32
-rw-r--r--arch/sparc/lib/NGcopy_to_user.S35
-rw-r--r--arch/sparc/lib/NGmemcpy.S425
-rw-r--r--arch/sparc/lib/NGpage.S137
-rw-r--r--arch/sparc/lib/NGpatch.S33
-rw-r--r--arch/sparc/lib/PeeCeeI.c211
-rw-r--r--arch/sparc/lib/U1copy_from_user.S29
-rw-r--r--arch/sparc/lib/U1copy_to_user.S29
-rw-r--r--arch/sparc/lib/U1memcpy.S563
-rw-r--r--arch/sparc/lib/U3copy_from_user.S18
-rw-r--r--arch/sparc/lib/U3copy_to_user.S29
-rw-r--r--arch/sparc/lib/U3memcpy.S422
-rw-r--r--arch/sparc/lib/U3patch.S33
-rw-r--r--arch/sparc/lib/VISsave.S144
-rw-r--r--arch/sparc/lib/ashldi3.S9
-rw-r--r--arch/sparc/lib/ashrdi3.S9
-rw-r--r--arch/sparc/lib/atomic.S99
-rw-r--r--arch/sparc/lib/atomic32.c25
-rw-r--r--arch/sparc/lib/atomic_64.S133
-rw-r--r--arch/sparc/lib/bitext.c12
-rw-r--r--arch/sparc/lib/bitops.S130
-rw-r--r--arch/sparc/lib/blockops.S12
-rw-r--r--arch/sparc/lib/bzero.S145
-rw-r--r--arch/sparc/lib/checksum_32.S (renamed from arch/sparc/lib/checksum.S)14
-rw-r--r--arch/sparc/lib/checksum_64.S173
-rw-r--r--arch/sparc/lib/clear_page.S103
-rw-r--r--arch/sparc/lib/cmpdi2.c27
-rw-r--r--arch/sparc/lib/copy_in_user.S92
-rw-r--r--arch/sparc/lib/copy_page.S250
-rw-r--r--arch/sparc/lib/csum_copy.S309
-rw-r--r--arch/sparc/lib/csum_copy_from_user.S21
-rw-r--r--arch/sparc/lib/csum_copy_to_user.S21
-rw-r--r--arch/sparc/lib/divdi3.S18
-rw-r--r--arch/sparc/lib/ffs.S84
-rw-r--r--arch/sparc/lib/hweight.S51
-rw-r--r--arch/sparc/lib/iomap.c23
-rw-r--r--arch/sparc/lib/ipcsum.S33
-rw-r--r--arch/sparc/lib/ksyms.c157
-rw-r--r--arch/sparc/lib/libgcc.h18
-rw-r--r--arch/sparc/lib/locks.S2
-rw-r--r--arch/sparc/lib/lshrdi3.S6
-rw-r--r--arch/sparc/lib/mcount.S129
-rw-r--r--arch/sparc/lib/memcmp.S329
-rw-r--r--arch/sparc/lib/memcpy.S807
-rw-r--r--arch/sparc/lib/memmove.S30
-rw-r--r--arch/sparc/lib/memscan_32.S (renamed from arch/sparc/lib/memscan.S)2
-rw-r--r--arch/sparc/lib/memscan_64.S129
-rw-r--r--arch/sparc/lib/memset.S5
-rw-r--r--arch/sparc/lib/mul.S137
-rw-r--r--arch/sparc/lib/muldi3.S4
-rw-r--r--arch/sparc/lib/rem.S384
-rw-r--r--arch/sparc/lib/rwsem.S204
-rw-r--r--arch/sparc/lib/sdiv.S381
-rw-r--r--arch/sparc/lib/strlen.S79
-rw-r--r--arch/sparc/lib/strlen_user.S109
-rw-r--r--arch/sparc/lib/strncmp_32.S (renamed from arch/sparc/lib/strncmp.S)10
-rw-r--r--arch/sparc/lib/strncmp_64.S30
-rw-r--r--arch/sparc/lib/strncpy_from_user.S47
-rw-r--r--arch/sparc/lib/ucmpdi2.c19
-rw-r--r--arch/sparc/lib/udiv.S357
-rw-r--r--arch/sparc/lib/udivdi3.S3
-rw-r--r--arch/sparc/lib/umul.S171
-rw-r--r--arch/sparc/lib/urem.S357
-rw-r--r--arch/sparc/lib/user_fixup.c71
-rw-r--r--arch/sparc/lib/xor.S636
-rw-r--r--arch/sparc/math-emu/Makefile6
-rw-r--r--arch/sparc/math-emu/ashldi3.S36
-rw-r--r--arch/sparc/math-emu/math_32.c (renamed from arch/sparc/math-emu/math.c)5
-rw-r--r--arch/sparc/math-emu/math_64.c524
-rw-r--r--arch/sparc/math-emu/sfp-util_32.h (renamed from arch/sparc/math-emu/sfp-util.h)20
-rw-r--r--arch/sparc/math-emu/sfp-util_64.h120
-rw-r--r--arch/sparc/mm/Makefile30
-rw-r--r--arch/sparc/mm/btfixup.c335
-rw-r--r--arch/sparc/mm/extable.c29
-rw-r--r--arch/sparc/mm/fault.c593
-rw-r--r--arch/sparc/mm/fault_32.c466
-rw-r--r--arch/sparc/mm/fault_64.c539
-rw-r--r--arch/sparc/mm/generic.c97
-rw-r--r--arch/sparc/mm/gup.c237
-rw-r--r--arch/sparc/mm/highmem.c88
-rw-r--r--arch/sparc/mm/hugetlbpage.c238
-rw-r--r--arch/sparc/mm/hypersparc.S10
-rw-r--r--arch/sparc/mm/init_32.c (renamed from arch/sparc/mm/init.c)215
-rw-r--r--arch/sparc/mm/init_64.c2701
-rw-r--r--arch/sparc/mm/init_64.h52
-rw-r--r--arch/sparc/mm/io-unit.c196
-rw-r--r--arch/sparc/mm/iommu.c225
-rw-r--r--arch/sparc/mm/leon_mm.c351
-rw-r--r--arch/sparc/mm/loadmmu.c44
-rw-r--r--arch/sparc/mm/mm_32.h24
-rw-r--r--arch/sparc/mm/nosrmmu.c59
-rw-r--r--arch/sparc/mm/nosun4c.c77
-rw-r--r--arch/sparc/mm/srmmu.c1651
-rw-r--r--arch/sparc/mm/srmmu_access.S82
-rw-r--r--arch/sparc/mm/sun4c.c2284
-rw-r--r--arch/sparc/mm/swift.S10
-rw-r--r--arch/sparc/mm/tlb.c243
-rw-r--r--arch/sparc/mm/tsb.c538
-rw-r--r--arch/sparc/mm/tsunami.S9
-rw-r--r--arch/sparc/mm/ultra.S878
-rw-r--r--arch/sparc/mm/viking.S13
-rw-r--r--arch/sparc/net/Makefile4
-rw-r--r--arch/sparc/net/bpf_jit.h68
-rw-r--r--arch/sparc/net/bpf_jit_asm.S205
-rw-r--r--arch/sparc/net/bpf_jit_comp.c816
-rw-r--r--arch/sparc/oprofile/Kconfig17
-rw-r--r--arch/sparc/oprofile/init.c68
-rw-r--r--arch/sparc/power/Makefile3
-rw-r--r--arch/sparc/power/hibernate.c42
-rw-r--r--arch/sparc/power/hibernate_asm.S131
-rw-r--r--arch/sparc/prom/Makefile18
-rw-r--r--arch/sparc/prom/bootstr_32.c (renamed from arch/sparc/prom/bootstr.c)21
-rw-r--r--arch/sparc/prom/bootstr_64.c40
-rw-r--r--arch/sparc/prom/cif.S48
-rw-r--r--arch/sparc/prom/console.c220
-rw-r--r--arch/sparc/prom/console_32.c56
-rw-r--r--arch/sparc/prom/console_64.c45
-rw-r--r--arch/sparc/prom/devmap.c54
-rw-r--r--arch/sparc/prom/devops.c89
-rw-r--r--arch/sparc/prom/init_32.c (renamed from arch/sparc/prom/init.c)39
-rw-r--r--arch/sparc/prom/init_64.c56
-rw-r--r--arch/sparc/prom/memory.c230
-rw-r--r--arch/sparc/prom/misc_32.c (renamed from arch/sparc/prom/misc.c)21
-rw-r--r--arch/sparc/prom/misc_64.c446
-rw-r--r--arch/sparc/prom/mp.c82
-rw-r--r--arch/sparc/prom/p1275.c55
-rw-r--r--arch/sparc/prom/palloc.c44
-rw-r--r--arch/sparc/prom/printf.c45
-rw-r--r--arch/sparc/prom/ranges.c21
-rw-r--r--arch/sparc/prom/segment.c29
-rw-r--r--arch/sparc/prom/sun4prom.c161
-rw-r--r--arch/sparc/prom/tree_32.c (renamed from arch/sparc/prom/tree.c)139
-rw-r--r--arch/sparc/prom/tree_64.c392
651 files changed, 108944 insertions, 27046 deletions
diff --git a/arch/sparc/Kbuild b/arch/sparc/Kbuild
new file mode 100644
index 00000000000..675afa285dd
--- /dev/null
+++ b/arch/sparc/Kbuild
@@ -0,0 +1,9 @@
+#
+# core part of the sparc kernel
+#
+
+obj-y += kernel/
+obj-y += mm/
+obj-y += math-emu/
+obj-y += net/
+obj-y += crypto/
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index bd992c0048f..407c87d9879 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -1,9 +1,121 @@
-# $Id: config.in,v 1.113 2002/01/24 22:14:44 davem Exp $
-# For a description of the syntax of this configuration file,
-# see Documentation/kbuild/kconfig-language.txt.
-#
+config 64BIT
+ bool "64-bit kernel" if ARCH = "sparc"
+ default ARCH = "sparc64"
+ help
+ SPARC is a family of RISC microprocessors designed and marketed by
+ Sun Microsystems, incorporated. They are very widely found in Sun
+ workstations and clones.
+
+ Say yes to build a 64-bit kernel - formerly known as sparc64
+ Say no to build a 32-bit kernel - formerly known as sparc
+
+config SPARC
+ bool
+ default y
+ select ARCH_MIGHT_HAVE_PC_PARPORT if SPARC64 && PCI
+ select ARCH_MIGHT_HAVE_PC_SERIO
+ select OF
+ select OF_PROMTREE
+ select HAVE_IDE
+ select HAVE_OPROFILE
+ select HAVE_ARCH_KGDB if !SMP || SPARC64
+ select HAVE_ARCH_TRACEHOOK
+ select SYSCTL_EXCEPTION_TRACE
+ select ARCH_WANT_OPTIONAL_GPIOLIB
+ select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
+ select RTC_CLASS
+ select RTC_DRV_M48T59
+ select HAVE_DMA_ATTRS
+ select HAVE_DMA_API_DEBUG
+ select HAVE_ARCH_JUMP_LABEL if SPARC64
+ select GENERIC_IRQ_SHOW
+ select ARCH_WANT_IPC_PARSE_VERSION
+ select GENERIC_PCI_IOMAP
+ select HAVE_NMI_WATCHDOG if SPARC64
+ select HAVE_BPF_JIT
+ select HAVE_DEBUG_BUGVERBOSE
+ select GENERIC_SMP_IDLE_THREAD
+ select GENERIC_CMOS_UPDATE
+ select GENERIC_CLOCKEVENTS
+ select GENERIC_STRNCPY_FROM_USER
+ select GENERIC_STRNLEN_USER
+ select MODULES_USE_ELF_RELA
+ select ODD_RT_SIGACTION
+ select OLD_SIGSUSPEND
+
+config SPARC32
+ def_bool !64BIT
+ select GENERIC_ATOMIC64
+ select CLZ_TAB
+ select HAVE_UID16
+ select OLD_SIGACTION
+
+config SPARC64
+ def_bool 64BIT
+ select HAVE_FUNCTION_TRACER
+ select HAVE_FUNCTION_GRAPH_TRACER
+ select HAVE_FUNCTION_GRAPH_FP_TEST
+ select HAVE_FUNCTION_TRACE_MCOUNT_TEST
+ select HAVE_KRETPROBES
+ select HAVE_KPROBES
+ select HAVE_RCU_TABLE_FREE if SMP
+ select HAVE_MEMBLOCK
+ select HAVE_MEMBLOCK_NODE_MAP
+ select HAVE_ARCH_TRANSPARENT_HUGEPAGE
+ select HAVE_DYNAMIC_FTRACE
+ select HAVE_FTRACE_MCOUNT_RECORD
+ select HAVE_SYSCALL_TRACEPOINTS
+ select HAVE_CONTEXT_TRACKING
+ select HAVE_DEBUG_KMEMLEAK
+ select RTC_DRV_CMOS
+ select RTC_DRV_BQ4802
+ select RTC_DRV_SUN4V
+ select RTC_DRV_STARFIRE
+ select HAVE_PERF_EVENTS
+ select PERF_USE_VMALLOC
+ select IRQ_PREFLOW_FASTEOI
+ select ARCH_HAVE_NMI_SAFE_CMPXCHG
+ select HAVE_C_RECORDMCOUNT
+ select NO_BOOTMEM
+ select HAVE_ARCH_AUDITSYSCALL
+ select ARCH_SUPPORTS_ATOMIC_RMW
+
+config ARCH_DEFCONFIG
+ string
+ default "arch/sparc/configs/sparc32_defconfig" if SPARC32
+ default "arch/sparc/configs/sparc64_defconfig" if SPARC64
+
+config IOMMU_HELPER
+ bool
+ default y if SPARC64
+
+config STACKTRACE_SUPPORT
+ bool
+ default y if SPARC64
+
+config LOCKDEP_SUPPORT
+ bool
+ default y if SPARC64
+
+config HAVE_LATENCYTOP_SUPPORT
+ bool
+ default y if SPARC64
+
+config ARCH_HIBERNATION_POSSIBLE
+ def_bool y if SPARC64
-mainmenu "Linux/SPARC Kernel Configuration"
+config AUDIT_ARCH
+ bool
+ default y
+
+config HAVE_SETUP_PER_CPU_AREA
+ def_bool y if SPARC64
+
+config NEED_PER_CPU_EMBED_FIRST_CHUNK
+ def_bool y if SPARC64
+
+config NEED_PER_CPU_PAGE_FIRST_CHUNK
+ def_bool y if SPARC64
config MMU
bool
@@ -11,113 +123,245 @@ config MMU
config HIGHMEM
bool
- default y
+ default y if SPARC32
config ZONE_DMA
bool
- default y
+ default y if SPARC32
+
+config NEED_DMA_MAP_STATE
+ def_bool y
+
+config NEED_SG_DMA_LENGTH
+ def_bool y
config GENERIC_ISA_DMA
bool
- default y
+ default y if SPARC32
+
+config ARCH_SUPPORTS_DEBUG_PAGEALLOC
+ def_bool y if SPARC64
source "init/Kconfig"
-menu "General machine setup"
+source "kernel/Kconfig.freezer"
+
+menu "Processor type and features"
config SMP
- bool "Symmetric multi-processing support (does not work on sun4/sun4c)"
+ bool "Symmetric multi-processing support"
---help---
This enables support for systems with more than one CPU. If you have
a system with only one CPU, say N. If you have a system with more
than one CPU, say Y.
- If you say N here, the kernel will run on single and multiprocessor
+ If you say N here, the kernel will run on uni- and multiprocessor
machines, but will use only one CPU of a multiprocessor machine. If
you say Y here, the kernel will run on many, but not all,
- singleprocessor machines. On a singleprocessor machine, the kernel
+ uniprocessor machines. On a uniprocessor machine, the kernel
will run faster if you say N here.
People using multiprocessor machines who say Y here should also say
Y to "Enhanced Real Time Clock Support", below. The "Advanced Power
Management" code will be disabled if you say Y here.
- See also the <file:Documentation/smp.txt>,
- <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at
- <http://www.tldp.org/docs.html#howto>.
+ See also <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO
+ available at <http://www.tldp.org/docs.html#howto>.
If you don't know what to do here, say N.
config NR_CPUS
- int "Maximum number of CPUs (2-32)"
- range 2 32
+ int "Maximum number of CPUs"
depends on SMP
- default "32"
+ range 2 32 if SPARC32
+ range 2 1024 if SPARC64
+ default 32 if SPARC32
+ default 64 if SPARC64
-config SPARC
+source kernel/Kconfig.hz
+
+config RWSEM_GENERIC_SPINLOCK
+ bool
+ default y if SPARC32
+
+config RWSEM_XCHGADD_ALGORITHM
+ bool
+ default y if SPARC64
+
+config GENERIC_HWEIGHT
bool
default y
-# Identify this as a Sparc32 build
-config SPARC32
+config GENERIC_CALIBRATE_DELAY
bool
default y
- help
- SPARC is a family of RISC microprocessors designed and marketed by
- Sun Microsystems, incorporated. They are very widely found in Sun
- workstations and clones. This port covers the original 32-bit SPARC;
- it is old and stable and usually considered one of the "big three"
- along with the Intel and Alpha ports. The UltraLinux project
- maintains both the SPARC32 and SPARC64 ports; its web page is
- available at <http://www.ultralinux.org/>.
-# Global things across all Sun machines.
-config ISA
+config ARCH_MAY_HAVE_PC_FDC
bool
- help
- ISA is found on Espresso only and is not supported currently.
- Say N
+ default y
-config EISA
+config EMULATED_CMPXCHG
bool
+ default y if SPARC32
help
- EISA is not supported.
- Say N
+ Sparc32 does not have a CAS instruction like sparc64. cmpxchg()
+ is emulated, and therefore it is not completely atomic.
+
+# Makefile helpers
+config SPARC32_SMP
+ bool
+ default y
+ depends on SPARC32 && SMP
-config MCA
+config SPARC64_SMP
bool
+ default y
+ depends on SPARC64 && SMP
+
+config EARLYFB
+ bool "Support for early boot text console"
+ default y
+ depends on SPARC64
help
- MCA is not supported.
- Say N
+ Say Y here to enable a faster early framebuffer boot console.
-config PCMCIA
- tristate
- ---help---
- Say Y here if you want to attach PCMCIA- or PC-cards to your Linux
- computer. These are credit-card size devices such as network cards,
- modems or hard drives often used with laptops computers. There are
- actually two varieties of these cards: the older 16 bit PCMCIA cards
- and the newer 32 bit CardBus cards. If you want to use CardBus
- cards, you need to say Y here and also to "CardBus support" below.
+config SECCOMP
+ bool "Enable seccomp to safely compute untrusted bytecode"
+ depends on SPARC64 && PROC_FS
+ default y
+ help
+ This kernel feature is useful for number crunching applications
+ that may need to compute untrusted bytecode during their
+ execution. By using pipes or other transports made available to
+ the process as file descriptors supporting the read/write
+ syscalls, it's possible to isolate those applications in
+ their own address space using seccomp. Once seccomp is
+ enabled via /proc/<pid>/seccomp, it cannot be disabled
+ and the task is only allowed to execute a few safe syscalls
+ defined by each seccomp mode.
+
+ If unsure, say Y. Only embedded should say N here.
+
+config HOTPLUG_CPU
+ bool "Support for hot-pluggable CPUs"
+ depends on SPARC64 && SMP
+ help
+ Say Y here to experiment with turning CPUs off and on. CPUs
+ can be controlled through /sys/devices/system/cpu/cpu#.
+ Say N if you want to disable CPU hotplug.
- To use your PC-cards, you will need supporting software from David
- Hinds' pcmcia-cs package (see the file <file:Documentation/Changes>
- for location). Please also read the PCMCIA-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
+if SPARC64
+source "drivers/cpufreq/Kconfig"
+endif
- To compile this driver as modules, choose M here: the
- modules will be called pcmcia_core and ds.
+config US3_MC
+ tristate "UltraSPARC-III Memory Controller driver"
+ depends on SPARC64
+ default y
+ help
+ This adds a driver for the UltraSPARC-III memory controller.
+ Loading this driver allows exact mnemonic strings to be
+ printed in the event of a memory error, so that the faulty DIMM
+ on the motherboard can be matched to the error.
-config SBUS
+ If in doubt, say Y, as this information can be very useful.
+
+# Global things across all Sun machines.
+config GENERIC_LOCKBREAK
bool
default y
+ depends on SPARC64 && SMP && PREEMPT
-config SBUSCHAR
- bool
+config NUMA
+ bool "NUMA support"
+ depends on SPARC64 && SMP
+
+config NODES_SHIFT
+ int
+ default "4"
+ depends on NEED_MULTIPLE_NODES
+
+# Some NUMA nodes have memory ranges that span
+# other nodes. Even though a pfn is valid and
+# between a node's start and end pfns, it may not
+# reside on that node. See memmap_init_zone()
+# for details.
+config NODES_SPAN_OTHER_NODES
+ def_bool y
+ depends on NEED_MULTIPLE_NODES
+
+config ARCH_SELECT_MEMORY_MODEL
+ def_bool y if SPARC64
+
+config ARCH_SPARSEMEM_ENABLE
+ def_bool y if SPARC64
+ select SPARSEMEM_VMEMMAP_ENABLE
+
+config ARCH_SPARSEMEM_DEFAULT
+ def_bool y if SPARC64
+
+source "mm/Kconfig"
+
+if SPARC64
+source "kernel/power/Kconfig"
+endif
+
+config SCHED_SMT
+ bool "SMT (Hyperthreading) scheduler support"
+ depends on SPARC64 && SMP
default y
+ help
+ SMT scheduler support improves the CPU scheduler's decision making
+ when dealing with SPARC cpus at a cost of slightly increased overhead
+ in some places. If unsure say N here.
+
+config SCHED_MC
+ bool "Multi-core scheduler support"
+ depends on SPARC64 && SMP
+ default y
+ help
+ Multi-core scheduler support improves the CPU scheduler's decision
+ making when dealing with multi-core CPU chips at a cost of slightly
+ increased overhead in some places. If unsure say N here.
+
+source "kernel/Kconfig.preempt"
+
+config CMDLINE_BOOL
+ bool "Default bootloader kernel arguments"
+ depends on SPARC64
+
+config CMDLINE
+ string "Initial kernel command string"
+ depends on CMDLINE_BOOL
+ default "console=ttyS0,9600 root=/dev/sda1"
+ help
+ Say Y here if you want to be able to pass default arguments to
+ the kernel. This will be overridden by the bootloader, if you
+ use one (such as SILO). This is most useful if you want to boot
+ a kernel from TFTP, and want default options to be available
+ with having them passed on the command line.
+
+ NOTE: This option WILL override the PROM bootargs setting!
+
+config SUN_PM
+ bool
+ default y if SPARC32
+ help
+ Enable power management and CPU standby features on supported
+ SPARC platforms.
+
+config SPARC_LED
+ tristate "Sun4m LED driver"
+ depends on SPARC32
+ help
+ This driver toggles the front-panel LED on sun4m systems
+ in a user-specifiable manner. Its state can be probed
+ by reading /proc/led and its blinking mode can be changed
+ via writes to /proc/led
config SERIAL_CONSOLE
bool
+ depends on SPARC32
default y
---help---
If you say Y here, it will be possible to use a serial port as the
@@ -139,73 +383,119 @@ config SERIAL_CONSOLE
If unsure, say N.
-config SUN_AUXIO
- bool
- default y
+config SPARC_LEON
+ bool "Sparc Leon processor family"
+ depends on SPARC32
+ select USB_EHCI_BIG_ENDIAN_MMIO
+ select USB_EHCI_BIG_ENDIAN_DESC
+ ---help---
+ If you say Y here if you are running on a SPARC-LEON processor.
+ The LEON processor is a synthesizable VHDL model of the
+ SPARC-v8 standard. LEON is part of the GRLIB collection of
+ IP cores that are distributed under GPL. GRLIB can be downloaded
+ from www.gaisler.com. You can download a sparc-linux cross-compilation
+ toolchain at www.gaisler.com.
+
+if SPARC_LEON
+menu "U-Boot options"
+
+config UBOOT_LOAD_ADDR
+ hex "uImage Load Address"
+ default 0x40004000
+ ---help---
+ U-Boot kernel load address, the address in physical address space
+ where u-boot will place the Linux kernel before booting it.
+ This address is normally the base address of main memory + 0x4000.
-config SUN_IO
- bool
- default y
+config UBOOT_FLASH_ADDR
+ hex "uImage.o Load Address"
+ default 0x00080000
+ ---help---
+ Optional setting only affecting the uImage.o ELF-image used to
+ download the uImage file to the target using a ELF-loader other than
+ U-Boot. It may for example be used to download an uImage to FLASH with
+ the GRMON utility before even starting u-boot.
+
+config UBOOT_ENTRY_ADDR
+ hex "uImage Entry Address"
+ default 0xf0004000
+ ---help---
+ Do not change this unless you know what you're doing. This is
+ hardcoded by the SPARC32 and LEON port.
-config RWSEM_GENERIC_SPINLOCK
- bool
- default y
+ This is the virtual address u-boot jumps to when booting the Linux
+ Kernel.
-config RWSEM_XCHGADD_ALGORITHM
- bool
+endmenu
+endif
-config GENERIC_FIND_NEXT_BIT
- bool
- default y
+endmenu
-config GENERIC_HWEIGHT
+menu "Bus options (PCI etc.)"
+config SBUS
bool
default y
-config GENERIC_CALIBRATE_DELAY
+config SBUSCHAR
bool
default y
-config ARCH_MAY_HAVE_PC_FDC
- bool
- default y
+config SUN_LDOMS
+ bool "Sun Logical Domains support"
+ depends on SPARC64
+ help
+ Say Y here is you want to support virtual devices via
+ Logical Domains.
-config ARCH_HAS_ILOG2_U32
- bool
- default n
+config PCI
+ bool "Support for PCI and PS/2 keyboard/mouse"
+ help
+ Find out whether your system includes a PCI bus. PCI is the name of
+ a bus system, i.e. the way the CPU talks to the other stuff inside
+ your box. If you say Y here, the kernel will include drivers and
+ infrastructure code to support PCI bus devices.
+
+ CONFIG_PCI is needed for all JavaStation's (including MrCoffee),
+ CP-1200, JavaEngine-1, Corona, Red October, and Serengeti SGSC.
+ All of these platforms are extremely obscure, so say N if unsure.
+
+config PCI_DOMAINS
+ def_bool PCI if SPARC64
-config ARCH_HAS_ILOG2_U64
+config PCI_SYSCALL
+ def_bool PCI
+
+config PCIC_PCI
bool
- default n
+ depends on PCI && SPARC32 && !SPARC_LEON
+ default y
-config SUN_PM
+config LEON_PCI
bool
+ depends on PCI && SPARC_LEON
default y
- help
- Enable power management and CPU standby features on supported
- SPARC platforms.
-config SUN4
- bool "Support for SUN4 machines (disables SUN4[CDM] support)"
- depends on !SMP
- default n
+config SPARC_GRPCI1
+ bool "GRPCI Host Bridge Support"
+ depends on LEON_PCI
+ default y
help
- Say Y here if, and only if, your machine is a sun4. Note that
- a kernel compiled with this option will run only on sun4.
- (And the current version will probably work only on sun4/330.)
-
-if !SUN4
-
-config PCI
- bool "Support for PCI and PS/2 keyboard/mouse"
+ Say Y here to include the GRPCI Host Bridge Driver. The GRPCI
+ PCI host controller is typically found in GRLIB SPARC32/LEON
+ systems. The driver has one property (all_pci_errors) controlled
+ from the bootloader that makes the GRPCI to generate interrupts
+ on detected PCI Parity and System errors.
+
+config SPARC_GRPCI2
+ bool "GRPCI2 Host Bridge Support"
+ depends on LEON_PCI
+ default y
help
- CONFIG_PCI is needed for all JavaStation's (including MrCoffee),
- CP-1200, JavaEngine-1, Corona, Red October, and Serengeti SGSC.
- All of these platforms are extremely obscure, so say N if unsure.
+ Say Y here to include the GRPCI2 Host Bridge Driver.
source "drivers/pci/Kconfig"
-endif
+source "drivers/pcmcia/Kconfig"
config SUN_OPENPROMFS
tristate "Openprom tree appears in /proc/openprom"
@@ -220,93 +510,49 @@ config SUN_OPENPROMFS
Only choose N if you know in advance that you will not need to modify
OpenPROM settings on the running system.
-config SPARC_LED
- tristate "Sun4m LED driver"
- help
- This driver toggles the front-panel LED on sun4m systems
- in a user-specifiable manner. Its state can be probed
- by reading /proc/led and its blinking mode can be changed
- via writes to /proc/led
-
-source "fs/Kconfig.binfmt"
-
-config SUNOS_EMUL
- bool "SunOS binary emulation"
- help
- This allows you to run most SunOS binaries. If you want to do this,
- say Y here and place appropriate files in /usr/gnemul/sunos. See
- <http://www.ultralinux.org/faq.html> for more information. If you
- want to run SunOS binaries on an Ultra you must also say Y to
- "Kernel support for 32-bit a.out binaries" above.
+# Makefile helpers
+config SPARC64_PCI
+ bool
+ default y
+ depends on SPARC64 && PCI
-source "mm/Kconfig"
+config SPARC64_PCI_MSI
+ bool
+ default y
+ depends on SPARC64_PCI && PCI_MSI
endmenu
-source "net/Kconfig"
-
-source "drivers/Kconfig"
-
-if !SUN4
-source "drivers/sbus/char/Kconfig"
-endif
+menu "Executable file formats"
-# This one must be before the filesystem configs. -DaveM
+source "fs/Kconfig.binfmt"
-menu "Unix98 PTY support"
+config COMPAT
+ bool
+ depends on SPARC64
+ default y
+ select COMPAT_BINFMT_ELF
+ select HAVE_UID16
+ select ARCH_WANT_OLD_COMPAT_IPC
+ select COMPAT_OLD_SIGACTION
-config UNIX98_PTYS
- bool "Unix98 PTY support"
- ---help---
- A pseudo terminal (PTY) is a software device consisting of two
- halves: a master and a slave. The slave device behaves identical to
- a physical terminal; the master device is used by a process to
- read data from and write data to the slave, thereby emulating a
- terminal. Typical programs for the master side are telnet servers
- and xterms.
-
- Linux has traditionally used the BSD-like names /dev/ptyxx for
- masters and /dev/ttyxx for slaves of pseudo terminals. This scheme
- has a number of problems. The GNU C library glibc 2.1 and later,
- however, supports the Unix98 naming standard: in order to acquire a
- pseudo terminal, a process opens /dev/ptmx; the number of the pseudo
- terminal is then made available to the process and the pseudo
- terminal slave can be accessed as /dev/pts/<number>. What was
- traditionally /dev/ttyp2 will then be /dev/pts/2, for example.
-
- The entries in /dev/pts/ are created on the fly by a virtual
- file system; therefore, if you say Y here you should say Y to
- "/dev/pts file system for Unix98 PTYs" as well.
-
- If you want to say Y here, you need to have the C library glibc 2.1
- or later (equal to libc-6.1, check with "ls -l /lib/libc.so.*").
- Read the instructions in <file:Documentation/Changes> pertaining to
- pseudo terminals. It's safe to say N.
-
-config UNIX98_PTY_COUNT
- int "Maximum number of Unix98 PTYs in use (0-2048)"
- depends on UNIX98_PTYS
- default "256"
- help
- The maximum number of Unix98 PTYs that can be used at any one time.
- The default is 256, and should be enough for desktop systems. Server
- machines which support incoming telnet/rlogin/ssh connections and/or
- serve several X terminals may want to increase this: every incoming
- connection and every xterm uses up one PTY.
+config SYSVIPC_COMPAT
+ bool
+ depends on COMPAT && SYSVIPC
+ default y
- When not in use, each additional set of 256 PTYs occupy
- approximately 8 KB of kernel memory on 32-bit architectures.
+config KEYS_COMPAT
+ def_bool y if COMPAT && KEYS
endmenu
-source "fs/Kconfig"
+source "net/Kconfig"
-menu "Instrumentation Support"
- depends on EXPERIMENTAL
+source "drivers/Kconfig"
-source "arch/sparc/oprofile/Kconfig"
+source "drivers/sbus/char/Kconfig"
-endmenu
+source "fs/Kconfig"
source "arch/sparc/Kconfig.debug"
diff --git a/arch/sparc/Kconfig.debug b/arch/sparc/Kconfig.debug
index 120f6b52934..6db35fba79f 100644
--- a/arch/sparc/Kconfig.debug
+++ b/arch/sparc/Kconfig.debug
@@ -1,14 +1,24 @@
menu "Kernel hacking"
+config TRACE_IRQFLAGS_SUPPORT
+ bool
+ default y
+
source "lib/Kconfig.debug"
-config DEBUG_STACK_USAGE
- bool "Enable stack utilization instrumentation"
- depends on DEBUG_KERNEL
- help
- Enables the display of the minimum amount of free stack which each
- task has ever had available in the sysrq-T and sysrq-P debug output.
+config DEBUG_DCFLUSH
+ bool "D-cache flush debugging"
+ depends on SPARC64 && DEBUG_KERNEL
+
+config MCOUNT
+ bool
+ depends on SPARC64
+ depends on FUNCTION_TRACER
+ default y
- This option will slow down process creation somewhat.
+config FRAME_POINTER
+ bool
+ depends on MCOUNT
+ default y
endmenu
diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile
index f33c3817f01..9ff423678cb 100644
--- a/arch/sparc/Makefile
+++ b/arch/sparc/Makefile
@@ -2,69 +2,91 @@
# sparc/Makefile
#
# Makefile for the architecture dependent flags and dependencies on the
-# Sparc.
-#
-# Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
+# Sparc and sparc64.
#
+# Copyright (C) 1994,1996,1998 David S. Miller (davem@caip.rutgers.edu)
+# Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz)
+
+# We are not yet configured - so test on arch
+ifeq ($(ARCH),sparc)
+ KBUILD_DEFCONFIG := sparc32_defconfig
+else
+ KBUILD_DEFCONFIG := sparc64_defconfig
+endif
+ifeq ($(CONFIG_SPARC32),y)
+#####
+# sparc32
#
-# Uncomment the first CFLAGS if you are doing kgdb source level
-# debugging of the kernel to get the proper debugging information.
-AS := $(AS) -32
-LDFLAGS := -m elf32_sparc
-CHECKFLAGS += -D__sparc__
+CHECKFLAGS += -D__sparc__
+LDFLAGS := -m elf32_sparc
+export BITS := 32
+UTS_MACHINE := sparc
-#CFLAGS := $(CFLAGS) -g -pipe -fcall-used-g5 -fcall-used-g7
-CFLAGS := $(CFLAGS) -m32 -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7
-AFLAGS := $(AFLAGS) -m32
+KBUILD_CFLAGS += -m32 -mcpu=v8 -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7
+KBUILD_AFLAGS += -m32 -Wa,-Av8
-#LDFLAGS_vmlinux = -N -Ttext 0xf0004000
-# Since 2.5.40, the first stage is left not btfix-ed.
-# Actual linking is done with "make image".
-LDFLAGS_vmlinux = -r
+else
+#####
+# sparc64
+#
-head-y := arch/sparc/kernel/head.o arch/sparc/kernel/init_task.o
-HEAD_Y := $(head-y)
+CHECKFLAGS += -D__sparc__ -D__sparc_v9__ -D__arch64__ -m64
+LDFLAGS := -m elf64_sparc
+export BITS := 64
+UTS_MACHINE := sparc64
-core-y += arch/sparc/kernel/ arch/sparc/mm/ arch/sparc/math-emu/
-libs-y += arch/sparc/prom/ arch/sparc/lib/
+KBUILD_CFLAGS += -m64 -pipe -mno-fpu -mcpu=ultrasparc -mcmodel=medlow
+KBUILD_CFLAGS += -ffixed-g4 -ffixed-g5 -fcall-used-g7 -Wno-sign-compare
+KBUILD_CFLAGS += -Wa,--undeclared-regs
+KBUILD_CFLAGS += $(call cc-option,-mtune=ultrasparc3)
+KBUILD_AFLAGS += -m64 -mcpu=ultrasparc -Wa,--undeclared-regs
-drivers-$(CONFIG_OPROFILE) += arch/sparc/oprofile/
+ifeq ($(CONFIG_MCOUNT),y)
+ KBUILD_CFLAGS += -pg
+endif
-# Export what is needed by arch/sparc/boot/Makefile
-# Renaming is done to avoid confusing pattern matching rules in 2.5.45 (multy-)
-INIT_Y := $(patsubst %/, %/built-in.o, $(init-y))
-CORE_Y := $(core-y)
-CORE_Y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
-CORE_Y := $(patsubst %/, %/built-in.o, $(CORE_Y))
-DRIVERS_Y := $(patsubst %/, %/built-in.o, $(drivers-y))
-NET_Y := $(patsubst %/, %/built-in.o, $(net-y))
-LIBS_Y1 := $(patsubst %/, %/lib.a, $(libs-y))
-LIBS_Y2 := $(patsubst %/, %/built-in.o, $(libs-y))
-LIBS_Y := $(LIBS_Y1) $(LIBS_Y2)
-
-ifdef CONFIG_KALLSYMS
-kallsyms.o := .tmp_kallsyms2.o
endif
-export INIT_Y CORE_Y DRIVERS_Y NET_Y LIBS_Y HEAD_Y kallsyms.o
+head-y := arch/sparc/kernel/head_$(BITS).o
-# Default target
-all: image
+# See arch/sparc/Kbuild for the core part of the kernel
+core-y += arch/sparc/
+
+libs-y += arch/sparc/prom/
+libs-y += arch/sparc/lib/
+
+drivers-$(CONFIG_PM) += arch/sparc/power/
+drivers-$(CONFIG_OPROFILE) += arch/sparc/oprofile/
boot := arch/sparc/boot
-image tftpboot.img: vmlinux
+# Default target
+all: zImage
+
+image zImage uImage tftpboot.img vmlinux.aout: vmlinux
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
archclean:
$(Q)$(MAKE) $(clean)=$(boot)
-CLEAN_FILES += arch/$(ARCH)/boot/System.map
+# This is the image used for packaging
+KBUILD_IMAGE := $(boot)/zImage
# Don't use tabs in echo arguments.
+ifeq ($(ARCH),sparc)
define archhelp
echo '* image - kernel image ($(boot)/image)'
+ echo '* zImage - stripped kernel image ($(boot)/zImage)'
+ echo ' uImage - U-Boot SPARC32 Image (only for LEON)'
echo ' tftpboot.img - image prepared for tftp'
endef
+else
+define archhelp
+ echo '* vmlinux - standard sparc64 kernel'
+ echo '* zImage - stripped and compressed sparc64 kernel ($(boot)/zImage)'
+ echo ' vmlinux.aout - a.out kernel for sparc64'
+ echo ' tftpboot.img - image prepared for tftp'
+endef
+endif
diff --git a/arch/sparc/boot/.gitignore b/arch/sparc/boot/.gitignore
new file mode 100644
index 00000000000..fc6f3986c76
--- /dev/null
+++ b/arch/sparc/boot/.gitignore
@@ -0,0 +1,8 @@
+btfix.S
+btfixupprep
+image
+zImage
+tftpboot.img
+vmlinux.aout
+piggyback
+
diff --git a/arch/sparc/boot/Makefile b/arch/sparc/boot/Makefile
index b365084316a..6e63afb128d 100644
--- a/arch/sparc/boot/Makefile
+++ b/arch/sparc/boot/Makefile
@@ -1,4 +1,3 @@
-# $Id: Makefile,v 1.10 2000/02/23 08:17:46 jj Exp $
# Makefile for the Sparc boot stuff.
#
# Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -7,52 +6,66 @@
ROOT_IMG := /usr/src/root.img
ELFTOAOUT := elftoaout
-hostprogs-y := piggyback btfixupprep
-targets := tftpboot.img btfix.o btfix.S image
+hostprogs-y := piggyback
+targets := tftpboot.img image zImage vmlinux.aout
+clean-files := System.map
quiet_cmd_elftoaout = ELFTOAOUT $@
cmd_elftoaout = $(ELFTOAOUT) $(obj)/image -o $@
quiet_cmd_piggy = PIGGY $@
- cmd_piggy = $(obj)/piggyback $@ $(obj)/System.map $(ROOT_IMG)
-quiet_cmd_btfix = BTFIX $@
- cmd_btfix = $(OBJDUMP) -x vmlinux | $(obj)/btfixupprep > $@
-quiet_cmd_sysmap = SYSMAP $(obj)/System.map
- cmd_sysmap = $(CONFIG_SHELL) $(srctree)/scripts/mksysmap
-quiet_cmd_image = LD $@
- cmd_image = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LDFLAGS_$(@F)) -o $@
-
-define rule_image
- $(if $($(quiet)cmd_image), \
- echo ' $($(quiet)cmd_image)' &&) \
- $(cmd_image); \
- $(if $($(quiet)cmd_sysmap), \
- echo ' $($(quiet)cmd_sysmap)' &&) \
- $(cmd_sysmap) $@ $(obj)/System.map; \
- if [ $$? -ne 0 ]; then \
- rm -f $@; \
- /bin/false; \
- fi; \
- echo 'cmd_$@ := $(cmd_image)' > $(@D)/.$(@F).cmd
-endef
-
-BTOBJS := $(HEAD_Y) $(INIT_Y)
-BTLIBS := $(CORE_Y) $(LIBS_Y) $(DRIVERS_Y) $(NET_Y)
-LDFLAGS_image := -T arch/sparc/kernel/vmlinux.lds $(BTOBJS) \
- --start-group $(BTLIBS) --end-group \
- $(kallsyms.o) $(obj)/btfix.o
-
-# Link the final image including btfixup'ed symbols.
-# This is a replacement for the link done in the top-level Makefile.
-# Note: No dependency on the prerequisite files since that would require
-# make to try check if they are updated - and due to changes
-# in gcc options (path for example) this would result in
-# these files being recompiled for each build.
-$(obj)/image: $(obj)/btfix.o FORCE
- $(call if_changed_rule,image)
-
-$(obj)/tftpboot.img: $(obj)/piggyback $(obj)/System.map $(obj)/image FORCE
+ cmd_piggy = $(obj)/piggyback $(BITS) $@ System.map $(ROOT_IMG)
+quiet_cmd_strip = STRIP $@
+ cmd_strip = $(STRIP) -R .comment -R .note -K sun4u_init -K _end -K _start $< -o $@
+
+ifeq ($(CONFIG_SPARC64),y)
+
+# Actual linking
+
+$(obj)/zImage: $(obj)/image
+ $(call if_changed,gzip)
+ @echo ' kernel: $@ is ready'
+
+$(obj)/vmlinux.aout: vmlinux FORCE
$(call if_changed,elftoaout)
- $(call if_changed,piggy)
+ @echo ' kernel: $@ is ready'
+else
+
+$(obj)/zImage: $(obj)/image
+ $(call if_changed,strip)
+ @echo ' kernel: $@ is ready'
+
+# The following lines make a readable image for U-Boot.
+# uImage - Binary file read by U-boot
+# uImage.o - object file of uImage for loading with a
+# flash programmer understanding ELF.
+
+OBJCOPYFLAGS_image.bin := -S -O binary -R .note -R .comment
+$(obj)/image.bin: $(obj)/image FORCE
+ $(call if_changed,objcopy)
-$(obj)/btfix.S: $(obj)/btfixupprep vmlinux FORCE
- $(call if_changed,btfix)
+$(obj)/image.gz: $(obj)/image.bin
+ $(call if_changed,gzip)
+
+UIMAGE_LOADADDR = $(CONFIG_UBOOT_LOAD_ADDR)
+UIMAGE_ENTRYADDR = $(CONFIG_UBOOT_ENTRY_ADDR)
+UIMAGE_COMPRESSION = gzip
+
+quiet_cmd_uimage.o = UIMAGE.O $@
+ cmd_uimage.o = $(LD) -Tdata $(CONFIG_UBOOT_FLASH_ADDR) \
+ -r -b binary $@ -o $@.o
+
+targets += uImage
+$(obj)/uImage: $(obj)/image.gz
+ $(call if_changed,uimage)
+ $(call if_changed,uimage.o)
+ @echo ' Image $@ is ready'
+
+endif
+
+$(obj)/image: vmlinux FORCE
+ $(call if_changed,strip)
+ @echo ' kernel: $@ is ready'
+
+$(obj)/tftpboot.img: $(obj)/image $(obj)/piggyback System.map $(ROOT_IMG) FORCE
+ $(call if_changed,elftoaout)
+ $(call if_changed,piggy)
diff --git a/arch/sparc/boot/btfixupprep.c b/arch/sparc/boot/btfixupprep.c
deleted file mode 100644
index dc7b0546e3b..00000000000
--- a/arch/sparc/boot/btfixupprep.c
+++ /dev/null
@@ -1,386 +0,0 @@
-/* $Id: btfixupprep.c,v 1.6 2001/08/22 15:27:47 davem Exp $
- Simple utility to prepare vmlinux image for sparc.
- Resolves all BTFIXUP uses and settings and creates
- a special .s object to link to the image.
-
- Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
-
- 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.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <malloc.h>
-
-#define MAXSYMS 1024
-
-static char *symtab = "SYMBOL TABLE:";
-static char *relrec = "RELOCATION RECORDS FOR [";
-static int rellen;
-static int symlen;
-int mode;
-
-struct _btfixup;
-
-typedef struct _btfixuprel {
- char *sect;
- unsigned long offset;
- struct _btfixup *f;
- int frel;
- struct _btfixuprel *next;
-} btfixuprel;
-
-typedef struct _btfixup {
- int type;
- int setinitval;
- unsigned int initval;
- char *initvalstr;
- char *name;
- btfixuprel *rel;
-} btfixup;
-
-btfixup array[MAXSYMS];
-int last = 0;
-char buffer[1024];
-unsigned long lastfoffset = -1;
-unsigned long lastfrelno;
-btfixup *lastf;
-
-void fatal(void) __attribute__((noreturn));
-void fatal(void)
-{
- fprintf(stderr, "Malformed output from objdump\n%s\n", buffer);
- exit(1);
-}
-
-btfixup *find(int type, char *name)
-{
- int i;
- for (i = 0; i < last; i++) {
- if (array[i].type == type && !strcmp(array[i].name, name))
- return array + i;
- }
- array[last].type = type;
- array[last].name = strdup(name);
- array[last].setinitval = 0;
- if (!array[last].name) fatal();
- array[last].rel = NULL;
- last++;
- if (last >= MAXSYMS) {
- fprintf(stderr, "Ugh. Something strange. More than %d different BTFIXUP symbols\n", MAXSYMS);
- exit(1);
- }
- return array + last - 1;
-}
-
-void set_mode (char *buffer)
-{
- for (mode = 0;; mode++)
- if (buffer[mode] < '0' || buffer[mode] > '9')
- break;
- if (mode != 8 && mode != 16)
- fatal();
-}
-
-
-int main(int argc,char **argv)
-{
- char *p, *q;
- char *sect;
- int i, j, k;
- unsigned int initval;
- int shift;
- btfixup *f;
- btfixuprel *r, **rr;
- unsigned long offset;
- char *initvalstr;
-
- symlen = strlen(symtab);
- while (fgets (buffer, 1024, stdin) != NULL)
- if (!strncmp (buffer, symtab, symlen))
- goto main0;
- fatal();
-main0:
- rellen = strlen(relrec);
- while (fgets (buffer, 1024, stdin) != NULL)
- if (!strncmp (buffer, relrec, rellen))
- goto main1;
- fatal();
-main1:
- sect = malloc(strlen (buffer + rellen) + 1);
- if (!sect) fatal();
- strcpy (sect, buffer + rellen);
- p = strchr (sect, ']');
- if (!p) fatal();
- *p = 0;
- if (fgets (buffer, 1024, stdin) == NULL)
- fatal();
- while (fgets (buffer, 1024, stdin) != NULL) {
- int nbase;
- if (!strncmp (buffer, relrec, rellen))
- goto main1;
- if (mode == 0)
- set_mode (buffer);
- p = strchr (buffer, '\n');
- if (p) *p = 0;
- if (strlen (buffer) < 22+mode)
- continue;
- if (strncmp (buffer + mode, " R_SPARC_", 9))
- continue;
- nbase = 27 - 8 + mode;
- if (buffer[nbase] != '_' || buffer[nbase+1] != '_' || buffer[nbase+2] != '_')
- continue;
- switch (buffer[nbase+3]) {
- case 'f': /* CALL */
- case 'b': /* BLACKBOX */
- case 's': /* SIMM13 */
- case 'a': /* HALF */
- case 'h': /* SETHI */
- case 'i': /* INT */
- break;
- default:
- continue;
- }
- p = strchr (buffer + nbase+5, '+');
- if (p) *p = 0;
- shift = nbase + 5;
- if (buffer[nbase+4] == 's' && buffer[nbase+5] == '_') {
- shift = nbase + 6;
- if (strcmp (sect, ".init.text")) {
- fprintf(stderr,
- "Wrong use of '%s' BTFIXUPSET in '%s' section.\n"
- "BTFIXUPSET_CALL can be used only in"
- " __init sections\n",
- buffer + shift, sect);
- exit(1);
- }
- } else if (buffer[nbase+4] != '_')
- continue;
- if (!strcmp (sect, ".text.exit"))
- continue;
- if (strcmp (sect, ".text") &&
- strcmp (sect, ".init.text") &&
- strcmp (sect, ".fixup") &&
- (strcmp (sect, "__ksymtab") || buffer[nbase+3] != 'f')) {
- if (buffer[nbase+3] == 'f')
- fprintf(stderr,
- "Wrong use of '%s' in '%s' section.\n"
- " It can be used only in .text, .init.text,"
- " .fixup and __ksymtab\n",
- buffer + shift, sect);
- else
- fprintf(stderr,
- "Wrong use of '%s' in '%s' section.\n"
- " It can be only used in .text, .init.text,"
- " and .fixup\n", buffer + shift, sect);
- exit(1);
- }
- p = strstr (buffer + shift, "__btset_");
- if (p && buffer[nbase+4] == 's') {
- fprintf(stderr, "__btset_ in BTFIXUP name can only be used when defining the variable, not for setting\n%s\n", buffer);
- exit(1);
- }
- initval = 0;
- initvalstr = NULL;
- if (p) {
- if (p[8] != '0' || p[9] != 'x') {
- fprintf(stderr, "Pre-initialized values can be only initialized with hexadecimal constants starting 0x\n%s\n", buffer);
- exit(1);
- }
- initval = strtoul(p + 10, &q, 16);
- if (*q || !initval) {
- fprintf(stderr, "Pre-initialized values can be only in the form name__btset_0xXXXXXXXX where X are hex digits.\nThey cannot be name__btset_0x00000000 though. Use BTFIXUPDEF_XX instead of BTFIXUPDEF_XX_INIT then.\n%s\n", buffer);
- exit(1);
- }
- initvalstr = p + 10;
- *p = 0;
- }
- f = find(buffer[nbase+3], buffer + shift);
- if (buffer[nbase+4] == 's')
- continue;
- switch (buffer[nbase+3]) {
- case 'f':
- if (initval) {
- fprintf(stderr, "Cannot use pre-initalized fixups for calls\n%s\n", buffer);
- exit(1);
- }
- if (!strcmp (sect, "__ksymtab")) {
- if (strncmp (buffer + mode+9, "32 ", 10)) {
- fprintf(stderr, "BTFIXUP_CALL in EXPORT_SYMBOL results in relocation other than R_SPARC_32\n\%s\n", buffer);
- exit(1);
- }
- } else if (strncmp (buffer + mode+9, "WDISP30 ", 10) &&
- strncmp (buffer + mode+9, "HI22 ", 10) &&
- strncmp (buffer + mode+9, "LO10 ", 10)) {
- fprintf(stderr, "BTFIXUP_CALL results in relocation other than R_SPARC_WDISP30, R_SPARC_HI22 or R_SPARC_LO10\n%s\n", buffer);
- exit(1);
- }
- break;
- case 'b':
- if (initval) {
- fprintf(stderr, "Cannot use pre-initialized fixups for blackboxes\n%s\n", buffer);
- exit(1);
- }
- if (strncmp (buffer + mode+9, "HI22 ", 10)) {
- fprintf(stderr, "BTFIXUP_BLACKBOX results in relocation other than R_SPARC_HI22\n%s\n", buffer);
- exit(1);
- }
- break;
- case 's':
- if (initval + 0x1000 >= 0x2000) {
- fprintf(stderr, "Wrong initializer for SIMM13. Has to be from $fffff000 to $00000fff\n%s\n", buffer);
- exit(1);
- }
- if (strncmp (buffer + mode+9, "13 ", 10)) {
- fprintf(stderr, "BTFIXUP_SIMM13 results in relocation other than R_SPARC_13\n%s\n", buffer);
- exit(1);
- }
- break;
- case 'a':
- if (initval + 0x1000 >= 0x2000 && (initval & 0x3ff)) {
- fprintf(stderr, "Wrong initializer for HALF.\n%s\n", buffer);
- exit(1);
- }
- if (strncmp (buffer + mode+9, "13 ", 10)) {
- fprintf(stderr, "BTFIXUP_HALF results in relocation other than R_SPARC_13\n%s\n", buffer);
- exit(1);
- }
- break;
- case 'h':
- if (initval & 0x3ff) {
- fprintf(stderr, "Wrong initializer for SETHI. Cannot have set low 10 bits\n%s\n", buffer);
- exit(1);
- }
- if (strncmp (buffer + mode+9, "HI22 ", 10)) {
- fprintf(stderr, "BTFIXUP_SETHI results in relocation other than R_SPARC_HI22\n%s\n", buffer);
- exit(1);
- }
- break;
- case 'i':
- if (initval) {
- fprintf(stderr, "Cannot use pre-initalized fixups for INT\n%s\n", buffer);
- exit(1);
- }
- if (strncmp (buffer + mode+9, "HI22 ", 10) && strncmp (buffer + mode+9, "LO10 ", 10)) {
- fprintf(stderr, "BTFIXUP_INT results in relocation other than R_SPARC_HI22 and R_SPARC_LO10\n%s\n", buffer);
- exit(1);
- }
- break;
- }
- if (!f->setinitval) {
- f->initval = initval;
- if (initvalstr) {
- f->initvalstr = strdup(initvalstr);
- if (!f->initvalstr) fatal();
- }
- f->setinitval = 1;
- } else if (f->initval != initval) {
- fprintf(stderr, "Btfixup %s previously used with initializer %s which doesn't match with current initializer\n%s\n",
- f->name, f->initvalstr ? : "0x00000000", buffer);
- exit(1);
- } else if (initval && strcmp(f->initvalstr, initvalstr)) {
- fprintf(stderr, "Btfixup %s previously used with initializer %s which doesn't match with current initializer.\n"
- "Initializers have to match literally as well.\n%s\n",
- f->name, f->initvalstr, buffer);
- exit(1);
- }
- offset = strtoul(buffer, &q, 16);
- if (q != buffer + mode || (!offset && (mode == 8 ? strncmp (buffer, "00000000 ", 9) : strncmp (buffer, "0000000000000000 ", 17)))) {
- fprintf(stderr, "Malformed relocation address in\n%s\n", buffer);
- exit(1);
- }
- for (k = 0, r = f->rel, rr = &f->rel; r; rr = &r->next, r = r->next, k++)
- if (r->offset == offset && !strcmp(r->sect, sect)) {
- fprintf(stderr, "Ugh. One address has two relocation records\n");
- exit(1);
- }
- *rr = malloc(sizeof(btfixuprel));
- if (!*rr) fatal();
- (*rr)->offset = offset;
- (*rr)->f = NULL;
- if (buffer[nbase+3] == 'f') {
- lastf = f;
- lastfoffset = offset;
- lastfrelno = k;
- } else if (lastfoffset + 4 == offset) {
- (*rr)->f = lastf;
- (*rr)->frel = lastfrelno;
- }
- (*rr)->sect = sect;
- (*rr)->next = NULL;
- }
- printf("! Generated by btfixupprep. Do not edit.\n\n");
- printf("\t.section\t\".data.init\",#alloc,#write\n\t.align\t4\n\n");
- printf("\t.global\t___btfixup_start\n___btfixup_start:\n\n");
- for (i = 0; i < last; i++) {
- f = array + i;
- printf("\t.global\t___%cs_%s\n", f->type, f->name);
- if (f->type == 'f')
- printf("___%cs_%s:\n\t.word 0x%08x,0,0,", f->type, f->name, f->type << 24);
- else
- printf("___%cs_%s:\n\t.word 0x%08x,0,", f->type, f->name, f->type << 24);
- for (j = 0, r = f->rel; r != NULL; j++, r = r->next);
- if (j)
- printf("%d\n\t.word\t", j * 2);
- else
- printf("0\n");
- for (r = f->rel, j--; r != NULL; j--, r = r->next) {
- if (!strcmp (r->sect, ".text"))
- printf ("_stext+0x%08lx", r->offset);
- else if (!strcmp (r->sect, ".init.text"))
- printf ("__init_begin+0x%08lx", r->offset);
- else if (!strcmp (r->sect, "__ksymtab"))
- printf ("__start___ksymtab+0x%08lx", r->offset);
- else if (!strcmp (r->sect, ".fixup"))
- printf ("__start___fixup+0x%08lx", r->offset);
- else
- fatal();
- if (f->type == 'f' || !r->f)
- printf (",0");
- else
- printf (",___fs_%s+0x%08x", r->f->name, (4 + r->frel*2)*4 + 4);
- if (j) printf (",");
- else printf ("\n");
- }
- printf("\n");
- }
- printf("\n\t.global\t___btfixup_end\n___btfixup_end:\n");
- printf("\n\n! Define undefined references\n\n");
- for (i = 0; i < last; i++) {
- f = array + i;
- if (f->type == 'f') {
- printf("\t.global\t___f_%s\n", f->name);
- printf("___f_%s:\n", f->name);
- }
- }
- printf("\tretl\n\t nop\n\n");
- for (i = 0; i < last; i++) {
- f = array + i;
- if (f->type != 'f') {
- if (!f->initval) {
- printf("\t.global\t___%c_%s\n", f->type, f->name);
- printf("___%c_%s = 0\n", f->type, f->name);
- } else {
- printf("\t.global\t___%c_%s__btset_0x%s\n", f->type, f->name, f->initvalstr);
- printf("___%c_%s__btset_0x%s = 0x%08x\n", f->type, f->name, f->initvalstr, f->initval);
- }
- }
- }
- printf("\n\n");
- exit(0);
-}
diff --git a/arch/sparc/boot/piggyback.c b/arch/sparc/boot/piggyback.c
index 6962cc68ed5..bb7c95161d7 100644
--- a/arch/sparc/boot/piggyback.c
+++ b/arch/sparc/boot/piggyback.c
@@ -1,15 +1,16 @@
-/* $Id: piggyback.c,v 1.4 2000/12/05 00:48:57 anton Exp $
+/*
Simple utility to make a single-image install kernel with initial ramdisk
for Sparc tftpbooting without need to set up nfs.
- Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
Pete Zaitcev <zaitcev@yahoo.com> endian fixes for cross-compiles, 2000.
+ Copyright (C) 2011 Sam Ravnborg <sam@ravnborg.org>
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.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
@@ -18,15 +19,16 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#include <stdio.h>
+
+#include <dirent.h>
+#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
-#include <dirent.h>
-#include <unistd.h>
-#include <stdlib.h>
+#include <stdio.h>
+
#include <sys/types.h>
#include <sys/stat.h>
@@ -35,17 +37,27 @@
* as PROM looks for a.out image only.
*/
-unsigned short ld2(char *p)
+#define AOUT_TEXT_OFFSET 32
+
+static int is64bit = 0;
+
+/* align to power-of-two size */
+static int align(int n)
{
- return (p[0] << 8) | p[1];
+ if (is64bit)
+ return (n + 0x1fff) & ~0x1fff;
+ else
+ return (n + 0xfff) & ~0xfff;
}
-unsigned int ld4(char *p)
+/* read two bytes as big endian */
+static unsigned short ld2(char *p)
{
- return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+ return (p[0] << 8) | p[1];
}
-void st4(char *p, unsigned int x)
+/* save 4 bytes as big endian */
+static void st4(char *p, unsigned int x)
{
p[0] = x >> 24;
p[1] = x >> 16;
@@ -53,85 +65,208 @@ void st4(char *p, unsigned int x)
p[3] = x;
}
-void usage(void)
+static void die(const char *str)
+{
+ perror(str);
+ exit(1);
+}
+
+static void usage(void)
{
/* fs_img.gz is an image of initial ramdisk. */
- fprintf(stderr, "Usage: piggyback vmlinux.aout System.map fs_img.gz\n");
+ fprintf(stderr, "Usage: piggyback bits vmlinux.aout System.map fs_img.gz\n");
fprintf(stderr, "\tKernel image will be modified in place.\n");
exit(1);
}
-void die(char *str)
+static int start_line(const char *line)
+{
+ if (strcmp(line + 10, " _start\n") == 0)
+ return 1;
+ else if (strcmp(line + 18, " _start\n") == 0)
+ return 1;
+ return 0;
+}
+
+static int end_line(const char *line)
{
- perror (str);
+ if (strcmp(line + 10, " _end\n") == 0)
+ return 1;
+ else if (strcmp (line + 18, " _end\n") == 0)
+ return 1;
+ return 0;
+}
+
+/*
+ * Find address for start and end in System.map.
+ * The file looks like this:
+ * f0004000 ... _start
+ * f0379f79 ... _end
+ * 1234567890123456
+ * ^coloumn 1
+ * There is support for 64 bit addresses too.
+ *
+ * Return 0 if either start or end is not found
+ */
+static int get_start_end(const char *filename, unsigned int *start,
+ unsigned int *end)
+{
+ FILE *map;
+ char buffer[1024];
+
+ *start = 0;
+ *end = 0;
+ map = fopen(filename, "r");
+ if (!map)
+ die(filename);
+ while (fgets(buffer, 1024, map)) {
+ if (start_line(buffer))
+ *start = strtoul(buffer, NULL, 16);
+ else if (end_line(buffer))
+ *end = strtoul(buffer, NULL, 16);
+ }
+ fclose (map);
+
+ if (*start == 0 || *end == 0)
+ return 0;
+
+ return 1;
+}
+
+#define LOOKBACK (128 * 4)
+#define BUFSIZE 1024
+/*
+ * Find the HdrS entry from head_32/head_64.
+ * We check if it is at the beginning of the file (sparc64 case)
+ * and if not we search for it.
+ * When we search do so in steps of 4 as HdrS is on a 4-byte aligned
+ * address (it is on same alignment as sparc instructions)
+ * Return the offset to the HdrS entry (as off_t)
+ */
+static off_t get_hdrs_offset(int kernelfd, const char *filename)
+{
+ char buffer[BUFSIZE];
+ off_t offset;
+ int i;
+
+ if (lseek(kernelfd, 0, SEEK_SET) < 0)
+ die("lseek");
+ if (read(kernelfd, buffer, BUFSIZE) != BUFSIZE)
+ die(filename);
+
+ if (buffer[40] == 'H' && buffer[41] == 'd' &&
+ buffer[42] == 'r' && buffer[43] == 'S') {
+ return 40;
+ } else {
+ /* Find the gokernel label */
+ /* Decode offset from branch instruction */
+ offset = ld2(buffer + AOUT_TEXT_OFFSET + 2) << 2;
+ /* Go back 512 bytes so we do not miss HdrS */
+ offset -= LOOKBACK;
+ /* skip a.out header */
+ offset += AOUT_TEXT_OFFSET;
+ if (lseek(kernelfd, offset, SEEK_SET) < 0)
+ die("lseek");
+ if (read(kernelfd, buffer, BUFSIZE) != BUFSIZE)
+ die(filename);
+
+ for (i = 0; i < LOOKBACK; i += 4) {
+ if (buffer[i + 0] == 'H' && buffer[i + 1] == 'd' &&
+ buffer[i + 2] == 'r' && buffer[i + 3] == 'S') {
+ return offset + i;
+ }
+ }
+ }
+ fprintf (stderr, "Couldn't find headers signature in %s\n", filename);
exit(1);
}
int main(int argc,char **argv)
{
static char aout_magic[] = { 0x01, 0x03, 0x01, 0x07 };
- unsigned char buffer[1024], *q, *r;
- unsigned int i, j, k, start, end, offset;
- FILE *map;
+ char buffer[1024];
+ unsigned int i, start, end;
+ off_t offset;
struct stat s;
int image, tail;
- if (argc != 4) usage();
- start = end = 0;
- if (stat (argv[3], &s) < 0) die (argv[3]);
- map = fopen (argv[2], "r");
- if (!map) die(argv[2]);
- while (fgets (buffer, 1024, map)) {
- if (!strcmp (buffer + 8, " T start\n") || !strcmp (buffer + 16, " T start\n"))
- start = strtoul (buffer, NULL, 16);
- else if (!strcmp (buffer + 8, " A end\n") || !strcmp (buffer + 16, " A end\n"))
- end = strtoul (buffer, NULL, 16);
- }
- fclose (map);
- if (!start || !end) {
- fprintf (stderr, "Could not determine start and end from System.map\n");
- exit(1);
- }
- if ((image = open(argv[1],O_RDWR)) < 0) die(argv[1]);
- if (read(image,buffer,512) != 512) die(argv[1]);
- if (memcmp (buffer, "\177ELF", 4) == 0) {
- q = buffer + ld4(buffer + 28);
- i = ld4(q + 4) + ld4(buffer + 24) - ld4(q + 8);
- if (lseek(image,i,0) < 0) die("lseek");
- if (read(image,buffer,512) != 512) die(argv[1]);
- j = 0;
- } else if (memcmp(buffer, aout_magic, 4) == 0) {
- i = j = 32;
- } else {
- fprintf (stderr, "Not ELF nor a.out. Don't blame me.\n");
+ if (argc != 5)
+ usage();
+ if (strcmp(argv[1], "64") == 0)
+ is64bit = 1;
+ if (stat (argv[4], &s) < 0)
+ die(argv[4]);
+
+ if (!get_start_end(argv[3], &start, &end)) {
+ fprintf(stderr, "Could not determine start and end from %s\n",
+ argv[3]);
exit(1);
}
- k = i;
- i += (ld2(buffer + j + 2)<<2) - 512;
- if (lseek(image,i,0) < 0) die("lseek");
- if (read(image,buffer,1024) != 1024) die(argv[1]);
- for (q = buffer, r = q + 512; q < r; q += 4) {
- if (*q == 'H' && q[1] == 'd' && q[2] == 'r' && q[3] == 'S')
- break;
- }
- if (q == r) {
- fprintf (stderr, "Couldn't find headers signature in the kernel.\n");
+ if ((image = open(argv[2], O_RDWR)) < 0)
+ die(argv[2]);
+ if (read(image, buffer, 512) != 512)
+ die(argv[2]);
+ if (memcmp(buffer, aout_magic, 4) != 0) {
+ fprintf (stderr, "Not a.out. Don't blame me.\n");
exit(1);
}
- offset = i + (q - buffer) + 10;
- if (lseek(image, offset, 0) < 0) die ("lseek");
+ /*
+ * We need to fill in values for
+ * sparc_ramdisk_image + sparc_ramdisk_size
+ * To locate these symbols search for the "HdrS" text which appear
+ * in the image a little before the gokernel symbol.
+ * See definition of these in init_32.S
+ */
+
+ offset = get_hdrs_offset(image, argv[2]);
+ /* skip HdrS + LINUX_VERSION_CODE + HdrS version */
+ offset += 10;
+
+ if (lseek(image, offset, 0) < 0)
+ die("lseek");
+ /*
+ * root_flags = 0
+ * root_dev = 1 (RAMDISK_MAJOR)
+ * ram_flags = 0
+ * sparc_ramdisk_image = "PAGE aligned address after _end")
+ * sparc_ramdisk_size = size of image
+ */
st4(buffer, 0);
st4(buffer + 4, 0x01000000);
- st4(buffer + 8, (end + 32 + 4095) & ~4095);
+ st4(buffer + 8, align(end + 32));
st4(buffer + 12, s.st_size);
- if (write(image,buffer+2,14) != 14) die (argv[1]);
- if (lseek(image, k - start + ((end + 32 + 4095) & ~4095), 0) < 0) die ("lseek");
- if ((tail = open(argv[3],O_RDONLY)) < 0) die(argv[3]);
- while ((i = read (tail,buffer,1024)) > 0)
- if (write(image,buffer,i) != i) die (argv[1]);
- if (close(image) < 0) die("close");
- if (close(tail) < 0) die("close");
- return 0;
+ if (write(image, buffer + 2, 14) != 14)
+ die(argv[2]);
+
+ /* For sparc64 update a_text and clear a_data + a_bss */
+ if (is64bit)
+ {
+ if (lseek(image, 4, 0) < 0)
+ die("lseek");
+ /* a_text */
+ st4(buffer, align(end + 32 + 8191) - (start & ~0x3fffffUL) +
+ s.st_size);
+ /* a_data */
+ st4(buffer + 4, 0);
+ /* a_bss */
+ st4(buffer + 8, 0);
+ if (write(image, buffer, 12) != 12)
+ die(argv[2]);
+ }
+
+ /* seek page aligned boundary in the image file and add boot image */
+ if (lseek(image, AOUT_TEXT_OFFSET - start + align(end + 32), 0) < 0)
+ die("lseek");
+ if ((tail = open(argv[4], O_RDONLY)) < 0)
+ die(argv[4]);
+ while ((i = read(tail, buffer, 1024)) > 0)
+ if (write(image, buffer, i) != i)
+ die(argv[2]);
+ if (close(image) < 0)
+ die("close");
+ if (close(tail) < 0)
+ die("close");
+ return 0;
}
diff --git a/arch/sparc/configs/sparc32_defconfig b/arch/sparc/configs/sparc32_defconfig
new file mode 100644
index 00000000000..fb23fd6b186
--- /dev/null
+++ b/arch/sparc/configs/sparc32_defconfig
@@ -0,0 +1,105 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PCI=y
+CONFIG_SUN_OPENPROMFS=m
+CONFIG_BINFMT_MISC=m
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+# CONFIG_INET_LRO is not set
+CONFIG_IPV6_PRIVACY=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NET_PKTGEN=m
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_DEV_SR=m
+CONFIG_CHR_DEV_SG=m
+CONFIG_SCSI_QLOGICPTI=m
+CONFIG_SCSI_SUNESP=y
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_SUNLANCE=y
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNBMAC=m
+CONFIG_SUNQE=m
+# CONFIG_WLAN is not set
+CONFIG_INPUT_JOYDEV=m
+CONFIG_INPUT_EVDEV=m
+CONFIG_INPUT_EVBUG=m
+CONFIG_KEYBOARD_ATKBD=m
+CONFIG_KEYBOARD_SUNKBD=m
+CONFIG_MOUSE_PS2=m
+CONFIG_MOUSE_SERIAL=m
+CONFIG_SERIO=m
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIAL_SUNZILOG=y
+CONFIG_SERIAL_SUNZILOG_CONSOLE=y
+CONFIG_SERIAL_SUNSU=y
+CONFIG_SERIAL_SUNSU_CONSOLE=y
+CONFIG_SPI=y
+CONFIG_SPI_XILINX=m
+CONFIG_SPI_XILINX_PLTFM=m
+CONFIG_SUN_OPENPROMIO=m
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+CONFIG_ISO9660_FS=m
+CONFIG_PROC_KCORE=y
+CONFIG_ROMFS_FS=m
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_NLS=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_KGDB=y
+CONFIG_KGDB_TESTS=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TWOFISH=m
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+CONFIG_LIBCRC32C=m
diff --git a/arch/sparc/configs/sparc64_defconfig b/arch/sparc/configs/sparc64_defconfig
new file mode 100644
index 00000000000..9d8521b8c85
--- /dev/null
+++ b/arch/sparc/configs/sparc64_defconfig
@@ -0,0 +1,242 @@
+CONFIG_64BIT=y
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_PERF_EVENTS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_KPROBES=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_SMP=y
+CONFIG_HZ_100=y
+CONFIG_HOTPLUG_CPU=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_NUMA=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=8192
+CONFIG_PREEMPT_VOLUNTARY=y
+CONFIG_SUN_LDOMS=y
+CONFIG_PCI=y
+CONFIG_PCI_MSI=y
+CONFIG_SUN_OPENPROMFS=m
+CONFIG_BINFMT_MISC=m
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=m
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_ARPD=y
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_VLAN_8021Q=m
+CONFIG_NET_PKTGEN=m
+CONFIG_NET_TCPPROBE=m
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_CONNECTOR=m
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_WCACHE=y
+CONFIG_ATA_OVER_ETH=m
+CONFIG_SUNVDC=m
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDECD=y
+CONFIG_BLK_DEV_ALI15X3=y
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_SPI_ATTRS=y
+CONFIG_SCSI_FC_ATTRS=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID456=m
+CONFIG_MD_MULTIPATH=m
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_NETDEVICES=y
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_SUNLANCE=m
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+CONFIG_SUNVNET=m
+CONFIG_NET_PCI=y
+CONFIG_E1000=m
+CONFIG_E1000E=m
+CONFIG_TIGON3=m
+CONFIG_BNX2=m
+CONFIG_NIU=m
+# CONFIG_WLAN is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_LKKBD=m
+CONFIG_KEYBOARD_SUNKBD=y
+CONFIG_MOUSE_SERIAL=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_SPARCSPKR=y
+# CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIO_PCIPS2=m
+CONFIG_SERIO_RAW=m
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_SUNSU=y
+CONFIG_SERIAL_SUNSU_CONSOLE=y
+CONFIG_SERIAL_SUNSAB=y
+CONFIG_SERIAL_SUNSAB_CONSOLE=y
+CONFIG_SERIAL_SUNHV=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_FB=y
+CONFIG_FB_TILEBLITTING=y
+CONFIG_FB_SBUS=y
+CONFIG_FB_CG6=y
+CONFIG_FB_FFB=y
+CONFIG_FB_XVR500=y
+CONFIG_FB_XVR2500=y
+CONFIG_FB_XVR1000=y
+CONFIG_FB_RADEON=y
+# CONFIG_FB_RADEON_BACKLIGHT is not set
+CONFIG_FB_ATY=y
+CONFIG_FB_ATY_GX=y
+# CONFIG_FB_ATY_BACKLIGHT is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_FONTS=y
+CONFIG_FONT_SUN8x16=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_SOUND=m
+CONFIG_SND=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_DUMMY=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+CONFIG_SND_ALI5451=m
+CONFIG_SND_SUN_CS4231=m
+CONFIG_USB_HIDDEV=y
+CONFIG_HID_DRAGONRISE=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_TWINHAN=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_ORTEK=y
+CONFIG_HID_PANTHERLORD=y
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_HID_GREENASIA=y
+CONFIG_HID_SMARTJOYPLUS=y
+CONFIG_HID_TOPSEED=y
+CONFIG_HID_THRUSTMASTER=y
+CONFIG_HID_ZEROPLUS=y
+CONFIG_USB=y
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_EHCI_HCD=m
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_UHCI_HCD=m
+CONFIG_USB_STORAGE=m
+CONFIG_SUN_OPENPROMIO=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_HUGETLBFS=y
+CONFIG_PRINTK_TIME=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_SCHEDSTATS=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_KEYS=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_TEST=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_XCBC=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRC16=m
+CONFIG_LIBCRC32C=m
diff --git a/arch/sparc/crypto/Makefile b/arch/sparc/crypto/Makefile
new file mode 100644
index 00000000000..5d469d81761
--- /dev/null
+++ b/arch/sparc/crypto/Makefile
@@ -0,0 +1,25 @@
+#
+# Arch-specific CryptoAPI modules.
+#
+
+obj-$(CONFIG_CRYPTO_SHA1_SPARC64) += sha1-sparc64.o
+obj-$(CONFIG_CRYPTO_SHA256_SPARC64) += sha256-sparc64.o
+obj-$(CONFIG_CRYPTO_SHA512_SPARC64) += sha512-sparc64.o
+obj-$(CONFIG_CRYPTO_MD5_SPARC64) += md5-sparc64.o
+
+obj-$(CONFIG_CRYPTO_AES_SPARC64) += aes-sparc64.o
+obj-$(CONFIG_CRYPTO_DES_SPARC64) += des-sparc64.o
+obj-$(CONFIG_CRYPTO_DES_SPARC64) += camellia-sparc64.o
+
+obj-$(CONFIG_CRYPTO_CRC32C_SPARC64) += crc32c-sparc64.o
+
+sha1-sparc64-y := sha1_asm.o sha1_glue.o
+sha256-sparc64-y := sha256_asm.o sha256_glue.o
+sha512-sparc64-y := sha512_asm.o sha512_glue.o
+md5-sparc64-y := md5_asm.o md5_glue.o
+
+aes-sparc64-y := aes_asm.o aes_glue.o
+des-sparc64-y := des_asm.o des_glue.o
+camellia-sparc64-y := camellia_asm.o camellia_glue.o
+
+crc32c-sparc64-y := crc32c_asm.o crc32c_glue.o
diff --git a/arch/sparc/crypto/aes_asm.S b/arch/sparc/crypto/aes_asm.S
new file mode 100644
index 00000000000..1cda8aa7cb8
--- /dev/null
+++ b/arch/sparc/crypto/aes_asm.S
@@ -0,0 +1,1543 @@
+#include <linux/linkage.h>
+#include <asm/visasm.h>
+
+#include "opcodes.h"
+
+#define ENCRYPT_TWO_ROUNDS(KEY_BASE, I0, I1, T0, T1) \
+ AES_EROUND01(KEY_BASE + 0, I0, I1, T0) \
+ AES_EROUND23(KEY_BASE + 2, I0, I1, T1) \
+ AES_EROUND01(KEY_BASE + 4, T0, T1, I0) \
+ AES_EROUND23(KEY_BASE + 6, T0, T1, I1)
+
+#define ENCRYPT_TWO_ROUNDS_2(KEY_BASE, I0, I1, I2, I3, T0, T1, T2, T3) \
+ AES_EROUND01(KEY_BASE + 0, I0, I1, T0) \
+ AES_EROUND23(KEY_BASE + 2, I0, I1, T1) \
+ AES_EROUND01(KEY_BASE + 0, I2, I3, T2) \
+ AES_EROUND23(KEY_BASE + 2, I2, I3, T3) \
+ AES_EROUND01(KEY_BASE + 4, T0, T1, I0) \
+ AES_EROUND23(KEY_BASE + 6, T0, T1, I1) \
+ AES_EROUND01(KEY_BASE + 4, T2, T3, I2) \
+ AES_EROUND23(KEY_BASE + 6, T2, T3, I3)
+
+#define ENCRYPT_TWO_ROUNDS_LAST(KEY_BASE, I0, I1, T0, T1) \
+ AES_EROUND01(KEY_BASE + 0, I0, I1, T0) \
+ AES_EROUND23(KEY_BASE + 2, I0, I1, T1) \
+ AES_EROUND01_L(KEY_BASE + 4, T0, T1, I0) \
+ AES_EROUND23_L(KEY_BASE + 6, T0, T1, I1)
+
+#define ENCRYPT_TWO_ROUNDS_LAST_2(KEY_BASE, I0, I1, I2, I3, T0, T1, T2, T3) \
+ AES_EROUND01(KEY_BASE + 0, I0, I1, T0) \
+ AES_EROUND23(KEY_BASE + 2, I0, I1, T1) \
+ AES_EROUND01(KEY_BASE + 0, I2, I3, T2) \
+ AES_EROUND23(KEY_BASE + 2, I2, I3, T3) \
+ AES_EROUND01_L(KEY_BASE + 4, T0, T1, I0) \
+ AES_EROUND23_L(KEY_BASE + 6, T0, T1, I1) \
+ AES_EROUND01_L(KEY_BASE + 4, T2, T3, I2) \
+ AES_EROUND23_L(KEY_BASE + 6, T2, T3, I3)
+
+ /* 10 rounds */
+#define ENCRYPT_128(KEY_BASE, I0, I1, T0, T1) \
+ ENCRYPT_TWO_ROUNDS(KEY_BASE + 0, I0, I1, T0, T1) \
+ ENCRYPT_TWO_ROUNDS(KEY_BASE + 8, I0, I1, T0, T1) \
+ ENCRYPT_TWO_ROUNDS(KEY_BASE + 16, I0, I1, T0, T1) \
+ ENCRYPT_TWO_ROUNDS(KEY_BASE + 24, I0, I1, T0, T1) \
+ ENCRYPT_TWO_ROUNDS_LAST(KEY_BASE + 32, I0, I1, T0, T1)
+
+#define ENCRYPT_128_2(KEY_BASE, I0, I1, I2, I3, T0, T1, T2, T3) \
+ ENCRYPT_TWO_ROUNDS_2(KEY_BASE + 0, I0, I1, I2, I3, T0, T1, T2, T3) \
+ ENCRYPT_TWO_ROUNDS_2(KEY_BASE + 8, I0, I1, I2, I3, T0, T1, T2, T3) \
+ ENCRYPT_TWO_ROUNDS_2(KEY_BASE + 16, I0, I1, I2, I3, T0, T1, T2, T3) \
+ ENCRYPT_TWO_ROUNDS_2(KEY_BASE + 24, I0, I1, I2, I3, T0, T1, T2, T3) \
+ ENCRYPT_TWO_ROUNDS_LAST_2(KEY_BASE + 32, I0, I1, I2, I3, T0, T1, T2, T3)
+
+ /* 12 rounds */
+#define ENCRYPT_192(KEY_BASE, I0, I1, T0, T1) \
+ ENCRYPT_TWO_ROUNDS(KEY_BASE + 0, I0, I1, T0, T1) \
+ ENCRYPT_TWO_ROUNDS(KEY_BASE + 8, I0, I1, T0, T1) \
+ ENCRYPT_TWO_ROUNDS(KEY_BASE + 16, I0, I1, T0, T1) \
+ ENCRYPT_TWO_ROUNDS(KEY_BASE + 24, I0, I1, T0, T1) \
+ ENCRYPT_TWO_ROUNDS(KEY_BASE + 32, I0, I1, T0, T1) \
+ ENCRYPT_TWO_ROUNDS_LAST(KEY_BASE + 40, I0, I1, T0, T1)
+
+#define ENCRYPT_192_2(KEY_BASE, I0, I1, I2, I3, T0, T1, T2, T3) \
+ ENCRYPT_TWO_ROUNDS_2(KEY_BASE + 0, I0, I1, I2, I3, T0, T1, T2, T3) \
+ ENCRYPT_TWO_ROUNDS_2(KEY_BASE + 8, I0, I1, I2, I3, T0, T1, T2, T3) \
+ ENCRYPT_TWO_ROUNDS_2(KEY_BASE + 16, I0, I1, I2, I3, T0, T1, T2, T3) \
+ ENCRYPT_TWO_ROUNDS_2(KEY_BASE + 24, I0, I1, I2, I3, T0, T1, T2, T3) \
+ ENCRYPT_TWO_ROUNDS_2(KEY_BASE + 32, I0, I1, I2, I3, T0, T1, T2, T3) \
+ ENCRYPT_TWO_ROUNDS_LAST_2(KEY_BASE + 40, I0, I1, I2, I3, T0, T1, T2, T3)
+
+ /* 14 rounds */
+#define ENCRYPT_256(KEY_BASE, I0, I1, T0, T1) \
+ ENCRYPT_TWO_ROUNDS(KEY_BASE + 0, I0, I1, T0, T1) \
+ ENCRYPT_TWO_ROUNDS(KEY_BASE + 8, I0, I1, T0, T1) \
+ ENCRYPT_TWO_ROUNDS(KEY_BASE + 16, I0, I1, T0, T1) \
+ ENCRYPT_TWO_ROUNDS(KEY_BASE + 24, I0, I1, T0, T1) \
+ ENCRYPT_TWO_ROUNDS(KEY_BASE + 32, I0, I1, T0, T1) \
+ ENCRYPT_TWO_ROUNDS(KEY_BASE + 40, I0, I1, T0, T1) \
+ ENCRYPT_TWO_ROUNDS_LAST(KEY_BASE + 48, I0, I1, T0, T1)
+
+#define ENCRYPT_256_TWO_ROUNDS_2(KEY_BASE, I0, I1, I2, I3, TMP_BASE) \
+ ENCRYPT_TWO_ROUNDS_2(KEY_BASE, I0, I1, I2, I3, \
+ TMP_BASE + 0, TMP_BASE + 2, TMP_BASE + 4, TMP_BASE + 6)
+
+#define ENCRYPT_256_2(KEY_BASE, I0, I1, I2, I3) \
+ ENCRYPT_256_TWO_ROUNDS_2(KEY_BASE + 0, I0, I1, I2, I3, KEY_BASE + 48) \
+ ldd [%o0 + 0xd0], %f56; \
+ ldd [%o0 + 0xd8], %f58; \
+ ENCRYPT_256_TWO_ROUNDS_2(KEY_BASE + 8, I0, I1, I2, I3, KEY_BASE + 0) \
+ ldd [%o0 + 0xe0], %f60; \
+ ldd [%o0 + 0xe8], %f62; \
+ ENCRYPT_256_TWO_ROUNDS_2(KEY_BASE + 16, I0, I1, I2, I3, KEY_BASE + 0) \
+ ENCRYPT_256_TWO_ROUNDS_2(KEY_BASE + 24, I0, I1, I2, I3, KEY_BASE + 0) \
+ ENCRYPT_256_TWO_ROUNDS_2(KEY_BASE + 32, I0, I1, I2, I3, KEY_BASE + 0) \
+ ENCRYPT_256_TWO_ROUNDS_2(KEY_BASE + 40, I0, I1, I2, I3, KEY_BASE + 0) \
+ AES_EROUND01(KEY_BASE + 48, I0, I1, KEY_BASE + 0) \
+ AES_EROUND23(KEY_BASE + 50, I0, I1, KEY_BASE + 2) \
+ AES_EROUND01(KEY_BASE + 48, I2, I3, KEY_BASE + 4) \
+ AES_EROUND23(KEY_BASE + 50, I2, I3, KEY_BASE + 6) \
+ AES_EROUND01_L(KEY_BASE + 52, KEY_BASE + 0, KEY_BASE + 2, I0) \
+ AES_EROUND23_L(KEY_BASE + 54, KEY_BASE + 0, KEY_BASE + 2, I1) \
+ ldd [%o0 + 0x10], %f8; \
+ ldd [%o0 + 0x18], %f10; \
+ AES_EROUND01_L(KEY_BASE + 52, KEY_BASE + 4, KEY_BASE + 6, I2) \
+ AES_EROUND23_L(KEY_BASE + 54, KEY_BASE + 4, KEY_BASE + 6, I3) \
+ ldd [%o0 + 0x20], %f12; \
+ ldd [%o0 + 0x28], %f14;
+
+#define DECRYPT_TWO_ROUNDS(KEY_BASE, I0, I1, T0, T1) \
+ AES_DROUND23(KEY_BASE + 0, I0, I1, T1) \
+ AES_DROUND01(KEY_BASE + 2, I0, I1, T0) \
+ AES_DROUND23(KEY_BASE + 4, T0, T1, I1) \
+ AES_DROUND01(KEY_BASE + 6, T0, T1, I0)
+
+#define DECRYPT_TWO_ROUNDS_2(KEY_BASE, I0, I1, I2, I3, T0, T1, T2, T3) \
+ AES_DROUND23(KEY_BASE + 0, I0, I1, T1) \
+ AES_DROUND01(KEY_BASE + 2, I0, I1, T0) \
+ AES_DROUND23(KEY_BASE + 0, I2, I3, T3) \
+ AES_DROUND01(KEY_BASE + 2, I2, I3, T2) \
+ AES_DROUND23(KEY_BASE + 4, T0, T1, I1) \
+ AES_DROUND01(KEY_BASE + 6, T0, T1, I0) \
+ AES_DROUND23(KEY_BASE + 4, T2, T3, I3) \
+ AES_DROUND01(KEY_BASE + 6, T2, T3, I2)
+
+#define DECRYPT_TWO_ROUNDS_LAST(KEY_BASE, I0, I1, T0, T1) \
+ AES_DROUND23(KEY_BASE + 0, I0, I1, T1) \
+ AES_DROUND01(KEY_BASE + 2, I0, I1, T0) \
+ AES_DROUND23_L(KEY_BASE + 4, T0, T1, I1) \
+ AES_DROUND01_L(KEY_BASE + 6, T0, T1, I0)
+
+#define DECRYPT_TWO_ROUNDS_LAST_2(KEY_BASE, I0, I1, I2, I3, T0, T1, T2, T3) \
+ AES_DROUND23(KEY_BASE + 0, I0, I1, T1) \
+ AES_DROUND01(KEY_BASE + 2, I0, I1, T0) \
+ AES_DROUND23(KEY_BASE + 0, I2, I3, T3) \
+ AES_DROUND01(KEY_BASE + 2, I2, I3, T2) \
+ AES_DROUND23_L(KEY_BASE + 4, T0, T1, I1) \
+ AES_DROUND01_L(KEY_BASE + 6, T0, T1, I0) \
+ AES_DROUND23_L(KEY_BASE + 4, T2, T3, I3) \
+ AES_DROUND01_L(KEY_BASE + 6, T2, T3, I2)
+
+ /* 10 rounds */
+#define DECRYPT_128(KEY_BASE, I0, I1, T0, T1) \
+ DECRYPT_TWO_ROUNDS(KEY_BASE + 0, I0, I1, T0, T1) \
+ DECRYPT_TWO_ROUNDS(KEY_BASE + 8, I0, I1, T0, T1) \
+ DECRYPT_TWO_ROUNDS(KEY_BASE + 16, I0, I1, T0, T1) \
+ DECRYPT_TWO_ROUNDS(KEY_BASE + 24, I0, I1, T0, T1) \
+ DECRYPT_TWO_ROUNDS_LAST(KEY_BASE + 32, I0, I1, T0, T1)
+
+#define DECRYPT_128_2(KEY_BASE, I0, I1, I2, I3, T0, T1, T2, T3) \
+ DECRYPT_TWO_ROUNDS_2(KEY_BASE + 0, I0, I1, I2, I3, T0, T1, T2, T3) \
+ DECRYPT_TWO_ROUNDS_2(KEY_BASE + 8, I0, I1, I2, I3, T0, T1, T2, T3) \
+ DECRYPT_TWO_ROUNDS_2(KEY_BASE + 16, I0, I1, I2, I3, T0, T1, T2, T3) \
+ DECRYPT_TWO_ROUNDS_2(KEY_BASE + 24, I0, I1, I2, I3, T0, T1, T2, T3) \
+ DECRYPT_TWO_ROUNDS_LAST_2(KEY_BASE + 32, I0, I1, I2, I3, T0, T1, T2, T3)
+
+ /* 12 rounds */
+#define DECRYPT_192(KEY_BASE, I0, I1, T0, T1) \
+ DECRYPT_TWO_ROUNDS(KEY_BASE + 0, I0, I1, T0, T1) \
+ DECRYPT_TWO_ROUNDS(KEY_BASE + 8, I0, I1, T0, T1) \
+ DECRYPT_TWO_ROUNDS(KEY_BASE + 16, I0, I1, T0, T1) \
+ DECRYPT_TWO_ROUNDS(KEY_BASE + 24, I0, I1, T0, T1) \
+ DECRYPT_TWO_ROUNDS(KEY_BASE + 32, I0, I1, T0, T1) \
+ DECRYPT_TWO_ROUNDS_LAST(KEY_BASE + 40, I0, I1, T0, T1)
+
+#define DECRYPT_192_2(KEY_BASE, I0, I1, I2, I3, T0, T1, T2, T3) \
+ DECRYPT_TWO_ROUNDS_2(KEY_BASE + 0, I0, I1, I2, I3, T0, T1, T2, T3) \
+ DECRYPT_TWO_ROUNDS_2(KEY_BASE + 8, I0, I1, I2, I3, T0, T1, T2, T3) \
+ DECRYPT_TWO_ROUNDS_2(KEY_BASE + 16, I0, I1, I2, I3, T0, T1, T2, T3) \
+ DECRYPT_TWO_ROUNDS_2(KEY_BASE + 24, I0, I1, I2, I3, T0, T1, T2, T3) \
+ DECRYPT_TWO_ROUNDS_2(KEY_BASE + 32, I0, I1, I2, I3, T0, T1, T2, T3) \
+ DECRYPT_TWO_ROUNDS_LAST_2(KEY_BASE + 40, I0, I1, I2, I3, T0, T1, T2, T3)
+
+ /* 14 rounds */
+#define DECRYPT_256(KEY_BASE, I0, I1, T0, T1) \
+ DECRYPT_TWO_ROUNDS(KEY_BASE + 0, I0, I1, T0, T1) \
+ DECRYPT_TWO_ROUNDS(KEY_BASE + 8, I0, I1, T0, T1) \
+ DECRYPT_TWO_ROUNDS(KEY_BASE + 16, I0, I1, T0, T1) \
+ DECRYPT_TWO_ROUNDS(KEY_BASE + 24, I0, I1, T0, T1) \
+ DECRYPT_TWO_ROUNDS(KEY_BASE + 32, I0, I1, T0, T1) \
+ DECRYPT_TWO_ROUNDS(KEY_BASE + 40, I0, I1, T0, T1) \
+ DECRYPT_TWO_ROUNDS_LAST(KEY_BASE + 48, I0, I1, T0, T1)
+
+#define DECRYPT_256_TWO_ROUNDS_2(KEY_BASE, I0, I1, I2, I3, TMP_BASE) \
+ DECRYPT_TWO_ROUNDS_2(KEY_BASE, I0, I1, I2, I3, \
+ TMP_BASE + 0, TMP_BASE + 2, TMP_BASE + 4, TMP_BASE + 6)
+
+#define DECRYPT_256_2(KEY_BASE, I0, I1, I2, I3) \
+ DECRYPT_256_TWO_ROUNDS_2(KEY_BASE + 0, I0, I1, I2, I3, KEY_BASE + 48) \
+ ldd [%o0 + 0x18], %f56; \
+ ldd [%o0 + 0x10], %f58; \
+ DECRYPT_256_TWO_ROUNDS_2(KEY_BASE + 8, I0, I1, I2, I3, KEY_BASE + 0) \
+ ldd [%o0 + 0x08], %f60; \
+ ldd [%o0 + 0x00], %f62; \
+ DECRYPT_256_TWO_ROUNDS_2(KEY_BASE + 16, I0, I1, I2, I3, KEY_BASE + 0) \
+ DECRYPT_256_TWO_ROUNDS_2(KEY_BASE + 24, I0, I1, I2, I3, KEY_BASE + 0) \
+ DECRYPT_256_TWO_ROUNDS_2(KEY_BASE + 32, I0, I1, I2, I3, KEY_BASE + 0) \
+ DECRYPT_256_TWO_ROUNDS_2(KEY_BASE + 40, I0, I1, I2, I3, KEY_BASE + 0) \
+ AES_DROUND23(KEY_BASE + 48, I0, I1, KEY_BASE + 2) \
+ AES_DROUND01(KEY_BASE + 50, I0, I1, KEY_BASE + 0) \
+ AES_DROUND23(KEY_BASE + 48, I2, I3, KEY_BASE + 6) \
+ AES_DROUND01(KEY_BASE + 50, I2, I3, KEY_BASE + 4) \
+ AES_DROUND23_L(KEY_BASE + 52, KEY_BASE + 0, KEY_BASE + 2, I1) \
+ AES_DROUND01_L(KEY_BASE + 54, KEY_BASE + 0, KEY_BASE + 2, I0) \
+ ldd [%o0 + 0xd8], %f8; \
+ ldd [%o0 + 0xd0], %f10; \
+ AES_DROUND23_L(KEY_BASE + 52, KEY_BASE + 4, KEY_BASE + 6, I3) \
+ AES_DROUND01_L(KEY_BASE + 54, KEY_BASE + 4, KEY_BASE + 6, I2) \
+ ldd [%o0 + 0xc8], %f12; \
+ ldd [%o0 + 0xc0], %f14;
+
+ .align 32
+ENTRY(aes_sparc64_key_expand)
+ /* %o0=input_key, %o1=output_key, %o2=key_len */
+ VISEntry
+ ld [%o0 + 0x00], %f0
+ ld [%o0 + 0x04], %f1
+ ld [%o0 + 0x08], %f2
+ ld [%o0 + 0x0c], %f3
+
+ std %f0, [%o1 + 0x00]
+ std %f2, [%o1 + 0x08]
+ add %o1, 0x10, %o1
+
+ cmp %o2, 24
+ bl 2f
+ nop
+
+ be 1f
+ nop
+
+ /* 256-bit key expansion */
+ ld [%o0 + 0x10], %f4
+ ld [%o0 + 0x14], %f5
+ ld [%o0 + 0x18], %f6
+ ld [%o0 + 0x1c], %f7
+
+ std %f4, [%o1 + 0x00]
+ std %f6, [%o1 + 0x08]
+ add %o1, 0x10, %o1
+
+ AES_KEXPAND1(0, 6, 0x0, 8)
+ AES_KEXPAND2(2, 8, 10)
+ AES_KEXPAND0(4, 10, 12)
+ AES_KEXPAND2(6, 12, 14)
+ AES_KEXPAND1(8, 14, 0x1, 16)
+ AES_KEXPAND2(10, 16, 18)
+ AES_KEXPAND0(12, 18, 20)
+ AES_KEXPAND2(14, 20, 22)
+ AES_KEXPAND1(16, 22, 0x2, 24)
+ AES_KEXPAND2(18, 24, 26)
+ AES_KEXPAND0(20, 26, 28)
+ AES_KEXPAND2(22, 28, 30)
+ AES_KEXPAND1(24, 30, 0x3, 32)
+ AES_KEXPAND2(26, 32, 34)
+ AES_KEXPAND0(28, 34, 36)
+ AES_KEXPAND2(30, 36, 38)
+ AES_KEXPAND1(32, 38, 0x4, 40)
+ AES_KEXPAND2(34, 40, 42)
+ AES_KEXPAND0(36, 42, 44)
+ AES_KEXPAND2(38, 44, 46)
+ AES_KEXPAND1(40, 46, 0x5, 48)
+ AES_KEXPAND2(42, 48, 50)
+ AES_KEXPAND0(44, 50, 52)
+ AES_KEXPAND2(46, 52, 54)
+ AES_KEXPAND1(48, 54, 0x6, 56)
+ AES_KEXPAND2(50, 56, 58)
+
+ std %f8, [%o1 + 0x00]
+ std %f10, [%o1 + 0x08]
+ std %f12, [%o1 + 0x10]
+ std %f14, [%o1 + 0x18]
+ std %f16, [%o1 + 0x20]
+ std %f18, [%o1 + 0x28]
+ std %f20, [%o1 + 0x30]
+ std %f22, [%o1 + 0x38]
+ std %f24, [%o1 + 0x40]
+ std %f26, [%o1 + 0x48]
+ std %f28, [%o1 + 0x50]
+ std %f30, [%o1 + 0x58]
+ std %f32, [%o1 + 0x60]
+ std %f34, [%o1 + 0x68]
+ std %f36, [%o1 + 0x70]
+ std %f38, [%o1 + 0x78]
+ std %f40, [%o1 + 0x80]
+ std %f42, [%o1 + 0x88]
+ std %f44, [%o1 + 0x90]
+ std %f46, [%o1 + 0x98]
+ std %f48, [%o1 + 0xa0]
+ std %f50, [%o1 + 0xa8]
+ std %f52, [%o1 + 0xb0]
+ std %f54, [%o1 + 0xb8]
+ std %f56, [%o1 + 0xc0]
+ ba,pt %xcc, 80f
+ std %f58, [%o1 + 0xc8]
+
+1:
+ /* 192-bit key expansion */
+ ld [%o0 + 0x10], %f4
+ ld [%o0 + 0x14], %f5
+
+ std %f4, [%o1 + 0x00]
+ add %o1, 0x08, %o1
+
+ AES_KEXPAND1(0, 4, 0x0, 6)
+ AES_KEXPAND2(2, 6, 8)
+ AES_KEXPAND2(4, 8, 10)
+ AES_KEXPAND1(6, 10, 0x1, 12)
+ AES_KEXPAND2(8, 12, 14)
+ AES_KEXPAND2(10, 14, 16)
+ AES_KEXPAND1(12, 16, 0x2, 18)
+ AES_KEXPAND2(14, 18, 20)
+ AES_KEXPAND2(16, 20, 22)
+ AES_KEXPAND1(18, 22, 0x3, 24)
+ AES_KEXPAND2(20, 24, 26)
+ AES_KEXPAND2(22, 26, 28)
+ AES_KEXPAND1(24, 28, 0x4, 30)
+ AES_KEXPAND2(26, 30, 32)
+ AES_KEXPAND2(28, 32, 34)
+ AES_KEXPAND1(30, 34, 0x5, 36)
+ AES_KEXPAND2(32, 36, 38)
+ AES_KEXPAND2(34, 38, 40)
+ AES_KEXPAND1(36, 40, 0x6, 42)
+ AES_KEXPAND2(38, 42, 44)
+ AES_KEXPAND2(40, 44, 46)
+ AES_KEXPAND1(42, 46, 0x7, 48)
+ AES_KEXPAND2(44, 48, 50)
+
+ std %f6, [%o1 + 0x00]
+ std %f8, [%o1 + 0x08]
+ std %f10, [%o1 + 0x10]
+ std %f12, [%o1 + 0x18]
+ std %f14, [%o1 + 0x20]
+ std %f16, [%o1 + 0x28]
+ std %f18, [%o1 + 0x30]
+ std %f20, [%o1 + 0x38]
+ std %f22, [%o1 + 0x40]
+ std %f24, [%o1 + 0x48]
+ std %f26, [%o1 + 0x50]
+ std %f28, [%o1 + 0x58]
+ std %f30, [%o1 + 0x60]
+ std %f32, [%o1 + 0x68]
+ std %f34, [%o1 + 0x70]
+ std %f36, [%o1 + 0x78]
+ std %f38, [%o1 + 0x80]
+ std %f40, [%o1 + 0x88]
+ std %f42, [%o1 + 0x90]
+ std %f44, [%o1 + 0x98]
+ std %f46, [%o1 + 0xa0]
+ std %f48, [%o1 + 0xa8]
+ ba,pt %xcc, 80f
+ std %f50, [%o1 + 0xb0]
+
+2:
+ /* 128-bit key expansion */
+ AES_KEXPAND1(0, 2, 0x0, 4)
+ AES_KEXPAND2(2, 4, 6)
+ AES_KEXPAND1(4, 6, 0x1, 8)
+ AES_KEXPAND2(6, 8, 10)
+ AES_KEXPAND1(8, 10, 0x2, 12)
+ AES_KEXPAND2(10, 12, 14)
+ AES_KEXPAND1(12, 14, 0x3, 16)
+ AES_KEXPAND2(14, 16, 18)
+ AES_KEXPAND1(16, 18, 0x4, 20)
+ AES_KEXPAND2(18, 20, 22)
+ AES_KEXPAND1(20, 22, 0x5, 24)
+ AES_KEXPAND2(22, 24, 26)
+ AES_KEXPAND1(24, 26, 0x6, 28)
+ AES_KEXPAND2(26, 28, 30)
+ AES_KEXPAND1(28, 30, 0x7, 32)
+ AES_KEXPAND2(30, 32, 34)
+ AES_KEXPAND1(32, 34, 0x8, 36)
+ AES_KEXPAND2(34, 36, 38)
+ AES_KEXPAND1(36, 38, 0x9, 40)
+ AES_KEXPAND2(38, 40, 42)
+
+ std %f4, [%o1 + 0x00]
+ std %f6, [%o1 + 0x08]
+ std %f8, [%o1 + 0x10]
+ std %f10, [%o1 + 0x18]
+ std %f12, [%o1 + 0x20]
+ std %f14, [%o1 + 0x28]
+ std %f16, [%o1 + 0x30]
+ std %f18, [%o1 + 0x38]
+ std %f20, [%o1 + 0x40]
+ std %f22, [%o1 + 0x48]
+ std %f24, [%o1 + 0x50]
+ std %f26, [%o1 + 0x58]
+ std %f28, [%o1 + 0x60]
+ std %f30, [%o1 + 0x68]
+ std %f32, [%o1 + 0x70]
+ std %f34, [%o1 + 0x78]
+ std %f36, [%o1 + 0x80]
+ std %f38, [%o1 + 0x88]
+ std %f40, [%o1 + 0x90]
+ std %f42, [%o1 + 0x98]
+80:
+ retl
+ VISExit
+ENDPROC(aes_sparc64_key_expand)
+
+ .align 32
+ENTRY(aes_sparc64_encrypt_128)
+ /* %o0=key, %o1=input, %o2=output */
+ VISEntry
+ ld [%o1 + 0x00], %f4
+ ld [%o1 + 0x04], %f5
+ ld [%o1 + 0x08], %f6
+ ld [%o1 + 0x0c], %f7
+ ldd [%o0 + 0x00], %f8
+ ldd [%o0 + 0x08], %f10
+ ldd [%o0 + 0x10], %f12
+ ldd [%o0 + 0x18], %f14
+ ldd [%o0 + 0x20], %f16
+ ldd [%o0 + 0x28], %f18
+ ldd [%o0 + 0x30], %f20
+ ldd [%o0 + 0x38], %f22
+ ldd [%o0 + 0x40], %f24
+ ldd [%o0 + 0x48], %f26
+ ldd [%o0 + 0x50], %f28
+ ldd [%o0 + 0x58], %f30
+ ldd [%o0 + 0x60], %f32
+ ldd [%o0 + 0x68], %f34
+ ldd [%o0 + 0x70], %f36
+ ldd [%o0 + 0x78], %f38
+ ldd [%o0 + 0x80], %f40
+ ldd [%o0 + 0x88], %f42
+ ldd [%o0 + 0x90], %f44
+ ldd [%o0 + 0x98], %f46
+ ldd [%o0 + 0xa0], %f48
+ ldd [%o0 + 0xa8], %f50
+ fxor %f8, %f4, %f4
+ fxor %f10, %f6, %f6
+ ENCRYPT_128(12, 4, 6, 0, 2)
+ st %f4, [%o2 + 0x00]
+ st %f5, [%o2 + 0x04]
+ st %f6, [%o2 + 0x08]
+ st %f7, [%o2 + 0x0c]
+ retl
+ VISExit
+ENDPROC(aes_sparc64_encrypt_128)
+
+ .align 32
+ENTRY(aes_sparc64_encrypt_192)
+ /* %o0=key, %o1=input, %o2=output */
+ VISEntry
+ ld [%o1 + 0x00], %f4
+ ld [%o1 + 0x04], %f5
+ ld [%o1 + 0x08], %f6
+ ld [%o1 + 0x0c], %f7
+
+ ldd [%o0 + 0x00], %f8
+ ldd [%o0 + 0x08], %f10
+
+ fxor %f8, %f4, %f4
+ fxor %f10, %f6, %f6
+
+ ldd [%o0 + 0x10], %f8
+ ldd [%o0 + 0x18], %f10
+ ldd [%o0 + 0x20], %f12
+ ldd [%o0 + 0x28], %f14
+ add %o0, 0x20, %o0
+
+ ENCRYPT_TWO_ROUNDS(8, 4, 6, 0, 2)
+
+ ldd [%o0 + 0x10], %f12
+ ldd [%o0 + 0x18], %f14
+ ldd [%o0 + 0x20], %f16
+ ldd [%o0 + 0x28], %f18
+ ldd [%o0 + 0x30], %f20
+ ldd [%o0 + 0x38], %f22
+ ldd [%o0 + 0x40], %f24
+ ldd [%o0 + 0x48], %f26
+ ldd [%o0 + 0x50], %f28
+ ldd [%o0 + 0x58], %f30
+ ldd [%o0 + 0x60], %f32
+ ldd [%o0 + 0x68], %f34
+ ldd [%o0 + 0x70], %f36
+ ldd [%o0 + 0x78], %f38
+ ldd [%o0 + 0x80], %f40
+ ldd [%o0 + 0x88], %f42
+ ldd [%o0 + 0x90], %f44
+ ldd [%o0 + 0x98], %f46
+ ldd [%o0 + 0xa0], %f48
+ ldd [%o0 + 0xa8], %f50
+
+
+ ENCRYPT_128(12, 4, 6, 0, 2)
+
+ st %f4, [%o2 + 0x00]
+ st %f5, [%o2 + 0x04]
+ st %f6, [%o2 + 0x08]
+ st %f7, [%o2 + 0x0c]
+
+ retl
+ VISExit
+ENDPROC(aes_sparc64_encrypt_192)
+
+ .align 32
+ENTRY(aes_sparc64_encrypt_256)
+ /* %o0=key, %o1=input, %o2=output */
+ VISEntry
+ ld [%o1 + 0x00], %f4
+ ld [%o1 + 0x04], %f5
+ ld [%o1 + 0x08], %f6
+ ld [%o1 + 0x0c], %f7
+
+ ldd [%o0 + 0x00], %f8
+ ldd [%o0 + 0x08], %f10
+
+ fxor %f8, %f4, %f4
+ fxor %f10, %f6, %f6
+
+ ldd [%o0 + 0x10], %f8
+
+ ldd [%o0 + 0x18], %f10
+ ldd [%o0 + 0x20], %f12
+ ldd [%o0 + 0x28], %f14
+ add %o0, 0x20, %o0
+
+ ENCRYPT_TWO_ROUNDS(8, 4, 6, 0, 2)
+
+ ldd [%o0 + 0x10], %f8
+
+ ldd [%o0 + 0x18], %f10
+ ldd [%o0 + 0x20], %f12
+ ldd [%o0 + 0x28], %f14
+ add %o0, 0x20, %o0
+
+ ENCRYPT_TWO_ROUNDS(8, 4, 6, 0, 2)
+
+ ldd [%o0 + 0x10], %f12
+ ldd [%o0 + 0x18], %f14
+ ldd [%o0 + 0x20], %f16
+ ldd [%o0 + 0x28], %f18
+ ldd [%o0 + 0x30], %f20
+ ldd [%o0 + 0x38], %f22
+ ldd [%o0 + 0x40], %f24
+ ldd [%o0 + 0x48], %f26
+ ldd [%o0 + 0x50], %f28
+ ldd [%o0 + 0x58], %f30
+ ldd [%o0 + 0x60], %f32
+ ldd [%o0 + 0x68], %f34
+ ldd [%o0 + 0x70], %f36
+ ldd [%o0 + 0x78], %f38
+ ldd [%o0 + 0x80], %f40
+ ldd [%o0 + 0x88], %f42
+ ldd [%o0 + 0x90], %f44
+ ldd [%o0 + 0x98], %f46
+ ldd [%o0 + 0xa0], %f48
+ ldd [%o0 + 0xa8], %f50
+
+ ENCRYPT_128(12, 4, 6, 0, 2)
+
+ st %f4, [%o2 + 0x00]
+ st %f5, [%o2 + 0x04]
+ st %f6, [%o2 + 0x08]
+ st %f7, [%o2 + 0x0c]
+
+ retl
+ VISExit
+ENDPROC(aes_sparc64_encrypt_256)
+
+ .align 32
+ENTRY(aes_sparc64_decrypt_128)
+ /* %o0=key, %o1=input, %o2=output */
+ VISEntry
+ ld [%o1 + 0x00], %f4
+ ld [%o1 + 0x04], %f5
+ ld [%o1 + 0x08], %f6
+ ld [%o1 + 0x0c], %f7
+ ldd [%o0 + 0xa0], %f8
+ ldd [%o0 + 0xa8], %f10
+ ldd [%o0 + 0x98], %f12
+ ldd [%o0 + 0x90], %f14
+ ldd [%o0 + 0x88], %f16
+ ldd [%o0 + 0x80], %f18
+ ldd [%o0 + 0x78], %f20
+ ldd [%o0 + 0x70], %f22
+ ldd [%o0 + 0x68], %f24
+ ldd [%o0 + 0x60], %f26
+ ldd [%o0 + 0x58], %f28
+ ldd [%o0 + 0x50], %f30
+ ldd [%o0 + 0x48], %f32
+ ldd [%o0 + 0x40], %f34
+ ldd [%o0 + 0x38], %f36
+ ldd [%o0 + 0x30], %f38
+ ldd [%o0 + 0x28], %f40
+ ldd [%o0 + 0x20], %f42
+ ldd [%o0 + 0x18], %f44
+ ldd [%o0 + 0x10], %f46
+ ldd [%o0 + 0x08], %f48
+ ldd [%o0 + 0x00], %f50
+ fxor %f8, %f4, %f4
+ fxor %f10, %f6, %f6
+ DECRYPT_128(12, 4, 6, 0, 2)
+ st %f4, [%o2 + 0x00]
+ st %f5, [%o2 + 0x04]
+ st %f6, [%o2 + 0x08]
+ st %f7, [%o2 + 0x0c]
+ retl
+ VISExit
+ENDPROC(aes_sparc64_decrypt_128)
+
+ .align 32
+ENTRY(aes_sparc64_decrypt_192)
+ /* %o0=key, %o1=input, %o2=output */
+ VISEntry
+ ld [%o1 + 0x00], %f4
+ ld [%o1 + 0x04], %f5
+ ld [%o1 + 0x08], %f6
+ ld [%o1 + 0x0c], %f7
+ ldd [%o0 + 0xc0], %f8
+ ldd [%o0 + 0xc8], %f10
+ ldd [%o0 + 0xb8], %f12
+ ldd [%o0 + 0xb0], %f14
+ ldd [%o0 + 0xa8], %f16
+ ldd [%o0 + 0xa0], %f18
+ fxor %f8, %f4, %f4
+ fxor %f10, %f6, %f6
+ ldd [%o0 + 0x98], %f20
+ ldd [%o0 + 0x90], %f22
+ ldd [%o0 + 0x88], %f24
+ ldd [%o0 + 0x80], %f26
+ DECRYPT_TWO_ROUNDS(12, 4, 6, 0, 2)
+ ldd [%o0 + 0x78], %f28
+ ldd [%o0 + 0x70], %f30
+ ldd [%o0 + 0x68], %f32
+ ldd [%o0 + 0x60], %f34
+ ldd [%o0 + 0x58], %f36
+ ldd [%o0 + 0x50], %f38
+ ldd [%o0 + 0x48], %f40
+ ldd [%o0 + 0x40], %f42
+ ldd [%o0 + 0x38], %f44
+ ldd [%o0 + 0x30], %f46
+ ldd [%o0 + 0x28], %f48
+ ldd [%o0 + 0x20], %f50
+ ldd [%o0 + 0x18], %f52
+ ldd [%o0 + 0x10], %f54
+ ldd [%o0 + 0x08], %f56
+ ldd [%o0 + 0x00], %f58
+ DECRYPT_128(20, 4, 6, 0, 2)
+ st %f4, [%o2 + 0x00]
+ st %f5, [%o2 + 0x04]
+ st %f6, [%o2 + 0x08]
+ st %f7, [%o2 + 0x0c]
+ retl
+ VISExit
+ENDPROC(aes_sparc64_decrypt_192)
+
+ .align 32
+ENTRY(aes_sparc64_decrypt_256)
+ /* %o0=key, %o1=input, %o2=output */
+ VISEntry
+ ld [%o1 + 0x00], %f4
+ ld [%o1 + 0x04], %f5
+ ld [%o1 + 0x08], %f6
+ ld [%o1 + 0x0c], %f7
+ ldd [%o0 + 0xe0], %f8
+ ldd [%o0 + 0xe8], %f10
+ ldd [%o0 + 0xd8], %f12
+ ldd [%o0 + 0xd0], %f14
+ ldd [%o0 + 0xc8], %f16
+ fxor %f8, %f4, %f4
+ ldd [%o0 + 0xc0], %f18
+ fxor %f10, %f6, %f6
+ ldd [%o0 + 0xb8], %f20
+ AES_DROUND23(12, 4, 6, 2)
+ ldd [%o0 + 0xb0], %f22
+ AES_DROUND01(14, 4, 6, 0)
+ ldd [%o0 + 0xa8], %f24
+ AES_DROUND23(16, 0, 2, 6)
+ ldd [%o0 + 0xa0], %f26
+ AES_DROUND01(18, 0, 2, 4)
+ ldd [%o0 + 0x98], %f12
+ AES_DROUND23(20, 4, 6, 2)
+ ldd [%o0 + 0x90], %f14
+ AES_DROUND01(22, 4, 6, 0)
+ ldd [%o0 + 0x88], %f16
+ AES_DROUND23(24, 0, 2, 6)
+ ldd [%o0 + 0x80], %f18
+ AES_DROUND01(26, 0, 2, 4)
+ ldd [%o0 + 0x78], %f20
+ AES_DROUND23(12, 4, 6, 2)
+ ldd [%o0 + 0x70], %f22
+ AES_DROUND01(14, 4, 6, 0)
+ ldd [%o0 + 0x68], %f24
+ AES_DROUND23(16, 0, 2, 6)
+ ldd [%o0 + 0x60], %f26
+ AES_DROUND01(18, 0, 2, 4)
+ ldd [%o0 + 0x58], %f28
+ AES_DROUND23(20, 4, 6, 2)
+ ldd [%o0 + 0x50], %f30
+ AES_DROUND01(22, 4, 6, 0)
+ ldd [%o0 + 0x48], %f32
+ AES_DROUND23(24, 0, 2, 6)
+ ldd [%o0 + 0x40], %f34
+ AES_DROUND01(26, 0, 2, 4)
+ ldd [%o0 + 0x38], %f36
+ AES_DROUND23(28, 4, 6, 2)
+ ldd [%o0 + 0x30], %f38
+ AES_DROUND01(30, 4, 6, 0)
+ ldd [%o0 + 0x28], %f40
+ AES_DROUND23(32, 0, 2, 6)
+ ldd [%o0 + 0x20], %f42
+ AES_DROUND01(34, 0, 2, 4)
+ ldd [%o0 + 0x18], %f44
+ AES_DROUND23(36, 4, 6, 2)
+ ldd [%o0 + 0x10], %f46
+ AES_DROUND01(38, 4, 6, 0)
+ ldd [%o0 + 0x08], %f48
+ AES_DROUND23(40, 0, 2, 6)
+ ldd [%o0 + 0x00], %f50
+ AES_DROUND01(42, 0, 2, 4)
+ AES_DROUND23(44, 4, 6, 2)
+ AES_DROUND01(46, 4, 6, 0)
+ AES_DROUND23_L(48, 0, 2, 6)
+ AES_DROUND01_L(50, 0, 2, 4)
+ st %f4, [%o2 + 0x00]
+ st %f5, [%o2 + 0x04]
+ st %f6, [%o2 + 0x08]
+ st %f7, [%o2 + 0x0c]
+ retl
+ VISExit
+ENDPROC(aes_sparc64_decrypt_256)
+
+ .align 32
+ENTRY(aes_sparc64_load_encrypt_keys_128)
+ /* %o0=key */
+ VISEntry
+ ldd [%o0 + 0x10], %f8
+ ldd [%o0 + 0x18], %f10
+ ldd [%o0 + 0x20], %f12
+ ldd [%o0 + 0x28], %f14
+ ldd [%o0 + 0x30], %f16
+ ldd [%o0 + 0x38], %f18
+ ldd [%o0 + 0x40], %f20
+ ldd [%o0 + 0x48], %f22
+ ldd [%o0 + 0x50], %f24
+ ldd [%o0 + 0x58], %f26
+ ldd [%o0 + 0x60], %f28
+ ldd [%o0 + 0x68], %f30
+ ldd [%o0 + 0x70], %f32
+ ldd [%o0 + 0x78], %f34
+ ldd [%o0 + 0x80], %f36
+ ldd [%o0 + 0x88], %f38
+ ldd [%o0 + 0x90], %f40
+ ldd [%o0 + 0x98], %f42
+ ldd [%o0 + 0xa0], %f44
+ retl
+ ldd [%o0 + 0xa8], %f46
+ENDPROC(aes_sparc64_load_encrypt_keys_128)
+
+ .align 32
+ENTRY(aes_sparc64_load_encrypt_keys_192)
+ /* %o0=key */
+ VISEntry
+ ldd [%o0 + 0x10], %f8
+ ldd [%o0 + 0x18], %f10
+ ldd [%o0 + 0x20], %f12
+ ldd [%o0 + 0x28], %f14
+ ldd [%o0 + 0x30], %f16
+ ldd [%o0 + 0x38], %f18
+ ldd [%o0 + 0x40], %f20
+ ldd [%o0 + 0x48], %f22
+ ldd [%o0 + 0x50], %f24
+ ldd [%o0 + 0x58], %f26
+ ldd [%o0 + 0x60], %f28
+ ldd [%o0 + 0x68], %f30
+ ldd [%o0 + 0x70], %f32
+ ldd [%o0 + 0x78], %f34
+ ldd [%o0 + 0x80], %f36
+ ldd [%o0 + 0x88], %f38
+ ldd [%o0 + 0x90], %f40
+ ldd [%o0 + 0x98], %f42
+ ldd [%o0 + 0xa0], %f44
+ ldd [%o0 + 0xa8], %f46
+ ldd [%o0 + 0xb0], %f48
+ ldd [%o0 + 0xb8], %f50
+ ldd [%o0 + 0xc0], %f52
+ retl
+ ldd [%o0 + 0xc8], %f54
+ENDPROC(aes_sparc64_load_encrypt_keys_192)
+
+ .align 32
+ENTRY(aes_sparc64_load_encrypt_keys_256)
+ /* %o0=key */
+ VISEntry
+ ldd [%o0 + 0x10], %f8
+ ldd [%o0 + 0x18], %f10
+ ldd [%o0 + 0x20], %f12
+ ldd [%o0 + 0x28], %f14
+ ldd [%o0 + 0x30], %f16
+ ldd [%o0 + 0x38], %f18
+ ldd [%o0 + 0x40], %f20
+ ldd [%o0 + 0x48], %f22
+ ldd [%o0 + 0x50], %f24
+ ldd [%o0 + 0x58], %f26
+ ldd [%o0 + 0x60], %f28
+ ldd [%o0 + 0x68], %f30
+ ldd [%o0 + 0x70], %f32
+ ldd [%o0 + 0x78], %f34
+ ldd [%o0 + 0x80], %f36
+ ldd [%o0 + 0x88], %f38
+ ldd [%o0 + 0x90], %f40
+ ldd [%o0 + 0x98], %f42
+ ldd [%o0 + 0xa0], %f44
+ ldd [%o0 + 0xa8], %f46
+ ldd [%o0 + 0xb0], %f48
+ ldd [%o0 + 0xb8], %f50
+ ldd [%o0 + 0xc0], %f52
+ ldd [%o0 + 0xc8], %f54
+ ldd [%o0 + 0xd0], %f56
+ ldd [%o0 + 0xd8], %f58
+ ldd [%o0 + 0xe0], %f60
+ retl
+ ldd [%o0 + 0xe8], %f62
+ENDPROC(aes_sparc64_load_encrypt_keys_256)
+
+ .align 32
+ENTRY(aes_sparc64_load_decrypt_keys_128)
+ /* %o0=key */
+ VISEntry
+ ldd [%o0 + 0x98], %f8
+ ldd [%o0 + 0x90], %f10
+ ldd [%o0 + 0x88], %f12
+ ldd [%o0 + 0x80], %f14
+ ldd [%o0 + 0x78], %f16
+ ldd [%o0 + 0x70], %f18
+ ldd [%o0 + 0x68], %f20
+ ldd [%o0 + 0x60], %f22
+ ldd [%o0 + 0x58], %f24
+ ldd [%o0 + 0x50], %f26
+ ldd [%o0 + 0x48], %f28
+ ldd [%o0 + 0x40], %f30
+ ldd [%o0 + 0x38], %f32
+ ldd [%o0 + 0x30], %f34
+ ldd [%o0 + 0x28], %f36
+ ldd [%o0 + 0x20], %f38
+ ldd [%o0 + 0x18], %f40
+ ldd [%o0 + 0x10], %f42
+ ldd [%o0 + 0x08], %f44
+ retl
+ ldd [%o0 + 0x00], %f46
+ENDPROC(aes_sparc64_load_decrypt_keys_128)
+
+ .align 32
+ENTRY(aes_sparc64_load_decrypt_keys_192)
+ /* %o0=key */
+ VISEntry
+ ldd [%o0 + 0xb8], %f8
+ ldd [%o0 + 0xb0], %f10
+ ldd [%o0 + 0xa8], %f12
+ ldd [%o0 + 0xa0], %f14
+ ldd [%o0 + 0x98], %f16
+ ldd [%o0 + 0x90], %f18
+ ldd [%o0 + 0x88], %f20
+ ldd [%o0 + 0x80], %f22
+ ldd [%o0 + 0x78], %f24
+ ldd [%o0 + 0x70], %f26
+ ldd [%o0 + 0x68], %f28
+ ldd [%o0 + 0x60], %f30
+ ldd [%o0 + 0x58], %f32
+ ldd [%o0 + 0x50], %f34
+ ldd [%o0 + 0x48], %f36
+ ldd [%o0 + 0x40], %f38
+ ldd [%o0 + 0x38], %f40
+ ldd [%o0 + 0x30], %f42
+ ldd [%o0 + 0x28], %f44
+ ldd [%o0 + 0x20], %f46
+ ldd [%o0 + 0x18], %f48
+ ldd [%o0 + 0x10], %f50
+ ldd [%o0 + 0x08], %f52
+ retl
+ ldd [%o0 + 0x00], %f54
+ENDPROC(aes_sparc64_load_decrypt_keys_192)
+
+ .align 32
+ENTRY(aes_sparc64_load_decrypt_keys_256)
+ /* %o0=key */
+ VISEntry
+ ldd [%o0 + 0xd8], %f8
+ ldd [%o0 + 0xd0], %f10
+ ldd [%o0 + 0xc8], %f12
+ ldd [%o0 + 0xc0], %f14
+ ldd [%o0 + 0xb8], %f16
+ ldd [%o0 + 0xb0], %f18
+ ldd [%o0 + 0xa8], %f20
+ ldd [%o0 + 0xa0], %f22
+ ldd [%o0 + 0x98], %f24
+ ldd [%o0 + 0x90], %f26
+ ldd [%o0 + 0x88], %f28
+ ldd [%o0 + 0x80], %f30
+ ldd [%o0 + 0x78], %f32
+ ldd [%o0 + 0x70], %f34
+ ldd [%o0 + 0x68], %f36
+ ldd [%o0 + 0x60], %f38
+ ldd [%o0 + 0x58], %f40
+ ldd [%o0 + 0x50], %f42
+ ldd [%o0 + 0x48], %f44
+ ldd [%o0 + 0x40], %f46
+ ldd [%o0 + 0x38], %f48
+ ldd [%o0 + 0x30], %f50
+ ldd [%o0 + 0x28], %f52
+ ldd [%o0 + 0x20], %f54
+ ldd [%o0 + 0x18], %f56
+ ldd [%o0 + 0x10], %f58
+ ldd [%o0 + 0x08], %f60
+ retl
+ ldd [%o0 + 0x00], %f62
+ENDPROC(aes_sparc64_load_decrypt_keys_256)
+
+ .align 32
+ENTRY(aes_sparc64_ecb_encrypt_128)
+ /* %o0=key, %o1=input, %o2=output, %o3=len */
+ ldx [%o0 + 0x00], %g1
+ subcc %o3, 0x10, %o3
+ be 10f
+ ldx [%o0 + 0x08], %g2
+1: ldx [%o1 + 0x00], %g3
+ ldx [%o1 + 0x08], %g7
+ ldx [%o1 + 0x10], %o4
+ ldx [%o1 + 0x18], %o5
+ xor %g1, %g3, %g3
+ xor %g2, %g7, %g7
+ MOVXTOD_G3_F4
+ MOVXTOD_G7_F6
+ xor %g1, %o4, %g3
+ xor %g2, %o5, %g7
+ MOVXTOD_G3_F60
+ MOVXTOD_G7_F62
+ ENCRYPT_128_2(8, 4, 6, 60, 62, 0, 2, 56, 58)
+ std %f4, [%o2 + 0x00]
+ std %f6, [%o2 + 0x08]
+ std %f60, [%o2 + 0x10]
+ std %f62, [%o2 + 0x18]
+ sub %o3, 0x20, %o3
+ add %o1, 0x20, %o1
+ brgz %o3, 1b
+ add %o2, 0x20, %o2
+ brlz,pt %o3, 11f
+ nop
+10: ldx [%o1 + 0x00], %g3
+ ldx [%o1 + 0x08], %g7
+ xor %g1, %g3, %g3
+ xor %g2, %g7, %g7
+ MOVXTOD_G3_F4
+ MOVXTOD_G7_F6
+ ENCRYPT_128(8, 4, 6, 0, 2)
+ std %f4, [%o2 + 0x00]
+ std %f6, [%o2 + 0x08]
+11: retl
+ nop
+ENDPROC(aes_sparc64_ecb_encrypt_128)
+
+ .align 32
+ENTRY(aes_sparc64_ecb_encrypt_192)
+ /* %o0=key, %o1=input, %o2=output, %o3=len */
+ ldx [%o0 + 0x00], %g1
+ subcc %o3, 0x10, %o3
+ be 10f
+ ldx [%o0 + 0x08], %g2
+1: ldx [%o1 + 0x00], %g3
+ ldx [%o1 + 0x08], %g7
+ ldx [%o1 + 0x10], %o4
+ ldx [%o1 + 0x18], %o5
+ xor %g1, %g3, %g3
+ xor %g2, %g7, %g7
+ MOVXTOD_G3_F4
+ MOVXTOD_G7_F6
+ xor %g1, %o4, %g3
+ xor %g2, %o5, %g7
+ MOVXTOD_G3_F60
+ MOVXTOD_G7_F62
+ ENCRYPT_192_2(8, 4, 6, 60, 62, 0, 2, 56, 58)
+ std %f4, [%o2 + 0x00]
+ std %f6, [%o2 + 0x08]
+ std %f60, [%o2 + 0x10]
+ std %f62, [%o2 + 0x18]
+ sub %o3, 0x20, %o3
+ add %o1, 0x20, %o1
+ brgz %o3, 1b
+ add %o2, 0x20, %o2
+ brlz,pt %o3, 11f
+ nop
+10: ldx [%o1 + 0x00], %g3
+ ldx [%o1 + 0x08], %g7
+ xor %g1, %g3, %g3
+ xor %g2, %g7, %g7
+ MOVXTOD_G3_F4
+ MOVXTOD_G7_F6
+ ENCRYPT_192(8, 4, 6, 0, 2)
+ std %f4, [%o2 + 0x00]
+ std %f6, [%o2 + 0x08]
+11: retl
+ nop
+ENDPROC(aes_sparc64_ecb_encrypt_192)
+
+ .align 32
+ENTRY(aes_sparc64_ecb_encrypt_256)
+ /* %o0=key, %o1=input, %o2=output, %o3=len */
+ ldx [%o0 + 0x00], %g1
+ subcc %o3, 0x10, %o3
+ be 10f
+ ldx [%o0 + 0x08], %g2
+1: ldx [%o1 + 0x00], %g3
+ ldx [%o1 + 0x08], %g7
+ ldx [%o1 + 0x10], %o4
+ ldx [%o1 + 0x18], %o5
+ xor %g1, %g3, %g3
+ xor %g2, %g7, %g7
+ MOVXTOD_G3_F4
+ MOVXTOD_G7_F6
+ xor %g1, %o4, %g3
+ xor %g2, %o5, %g7
+ MOVXTOD_G3_F0
+ MOVXTOD_G7_F2
+ ENCRYPT_256_2(8, 4, 6, 0, 2)
+ std %f4, [%o2 + 0x00]
+ std %f6, [%o2 + 0x08]
+ std %f0, [%o2 + 0x10]
+ std %f2, [%o2 + 0x18]
+ sub %o3, 0x20, %o3
+ add %o1, 0x20, %o1
+ brgz %o3, 1b
+ add %o2, 0x20, %o2
+ brlz,pt %o3, 11f
+ nop
+10: ldd [%o0 + 0xd0], %f56
+ ldd [%o0 + 0xd8], %f58
+ ldd [%o0 + 0xe0], %f60
+ ldd [%o0 + 0xe8], %f62
+ ldx [%o1 + 0x00], %g3
+ ldx [%o1 + 0x08], %g7
+ xor %g1, %g3, %g3
+ xor %g2, %g7, %g7
+ MOVXTOD_G3_F4
+ MOVXTOD_G7_F6
+ ENCRYPT_256(8, 4, 6, 0, 2)
+ std %f4, [%o2 + 0x00]
+ std %f6, [%o2 + 0x08]
+11: retl
+ nop
+ENDPROC(aes_sparc64_ecb_encrypt_256)
+
+ .align 32
+ENTRY(aes_sparc64_ecb_decrypt_128)
+ /* %o0=&key[key_len], %o1=input, %o2=output, %o3=len */
+ ldx [%o0 - 0x10], %g1
+ subcc %o3, 0x10, %o3
+ be 10f
+ ldx [%o0 - 0x08], %g2
+1: ldx [%o1 + 0x00], %g3
+ ldx [%o1 + 0x08], %g7
+ ldx [%o1 + 0x10], %o4
+ ldx [%o1 + 0x18], %o5
+ xor %g1, %g3, %g3
+ xor %g2, %g7, %g7
+ MOVXTOD_G3_F4
+ MOVXTOD_G7_F6
+ xor %g1, %o4, %g3
+ xor %g2, %o5, %g7
+ MOVXTOD_G3_F60
+ MOVXTOD_G7_F62
+ DECRYPT_128_2(8, 4, 6, 60, 62, 0, 2, 56, 58)
+ std %f4, [%o2 + 0x00]
+ std %f6, [%o2 + 0x08]
+ std %f60, [%o2 + 0x10]
+ std %f62, [%o2 + 0x18]
+ sub %o3, 0x20, %o3
+ add %o1, 0x20, %o1
+ brgz,pt %o3, 1b
+ add %o2, 0x20, %o2
+ brlz,pt %o3, 11f
+ nop
+10: ldx [%o1 + 0x00], %g3
+ ldx [%o1 + 0x08], %g7
+ xor %g1, %g3, %g3
+ xor %g2, %g7, %g7
+ MOVXTOD_G3_F4
+ MOVXTOD_G7_F6
+ DECRYPT_128(8, 4, 6, 0, 2)
+ std %f4, [%o2 + 0x00]
+ std %f6, [%o2 + 0x08]
+11: retl
+ nop
+ENDPROC(aes_sparc64_ecb_decrypt_128)
+
+ .align 32
+ENTRY(aes_sparc64_ecb_decrypt_192)
+ /* %o0=&key[key_len], %o1=input, %o2=output, %o3=len */
+ ldx [%o0 - 0x10], %g1
+ subcc %o3, 0x10, %o3
+ be 10f
+ ldx [%o0 - 0x08], %g2
+1: ldx [%o1 + 0x00], %g3
+ ldx [%o1 + 0x08], %g7
+ ldx [%o1 + 0x10], %o4
+ ldx [%o1 + 0x18], %o5
+ xor %g1, %g3, %g3
+ xor %g2, %g7, %g7
+ MOVXTOD_G3_F4
+ MOVXTOD_G7_F6
+ xor %g1, %o4, %g3
+ xor %g2, %o5, %g7
+ MOVXTOD_G3_F60
+ MOVXTOD_G7_F62
+ DECRYPT_192_2(8, 4, 6, 60, 62, 0, 2, 56, 58)
+ std %f4, [%o2 + 0x00]
+ std %f6, [%o2 + 0x08]
+ std %f60, [%o2 + 0x10]
+ std %f62, [%o2 + 0x18]
+ sub %o3, 0x20, %o3
+ add %o1, 0x20, %o1
+ brgz,pt %o3, 1b
+ add %o2, 0x20, %o2
+ brlz,pt %o3, 11f
+ nop
+10: ldx [%o1 + 0x00], %g3
+ ldx [%o1 + 0x08], %g7
+ xor %g1, %g3, %g3
+ xor %g2, %g7, %g7
+ MOVXTOD_G3_F4
+ MOVXTOD_G7_F6
+ DECRYPT_192(8, 4, 6, 0, 2)
+ std %f4, [%o2 + 0x00]
+ std %f6, [%o2 + 0x08]
+11: retl
+ nop
+ENDPROC(aes_sparc64_ecb_decrypt_192)
+
+ .align 32
+ENTRY(aes_sparc64_ecb_decrypt_256)
+ /* %o0=&key[key_len], %o1=input, %o2=output, %o3=len */
+ ldx [%o0 - 0x10], %g1
+ subcc %o3, 0x10, %o3
+ ldx [%o0 - 0x08], %g2
+ be 10f
+ sub %o0, 0xf0, %o0
+1: ldx [%o1 + 0x00], %g3
+ ldx [%o1 + 0x08], %g7
+ ldx [%o1 + 0x10], %o4
+ ldx [%o1 + 0x18], %o5
+ xor %g1, %g3, %g3
+ xor %g2, %g7, %g7
+ MOVXTOD_G3_F4
+ MOVXTOD_G7_F6
+ xor %g1, %o4, %g3
+ xor %g2, %o5, %g7
+ MOVXTOD_G3_F0
+ MOVXTOD_G7_F2
+ DECRYPT_256_2(8, 4, 6, 0, 2)
+ std %f4, [%o2 + 0x00]
+ std %f6, [%o2 + 0x08]
+ std %f0, [%o2 + 0x10]
+ std %f2, [%o2 + 0x18]
+ sub %o3, 0x20, %o3
+ add %o1, 0x20, %o1
+ brgz,pt %o3, 1b
+ add %o2, 0x20, %o2
+ brlz,pt %o3, 11f
+ nop
+10: ldd [%o0 + 0x18], %f56
+ ldd [%o0 + 0x10], %f58
+ ldd [%o0 + 0x08], %f60
+ ldd [%o0 + 0x00], %f62
+ ldx [%o1 + 0x00], %g3
+ ldx [%o1 + 0x08], %g7
+ xor %g1, %g3, %g3
+ xor %g2, %g7, %g7
+ MOVXTOD_G3_F4
+ MOVXTOD_G7_F6
+ DECRYPT_256(8, 4, 6, 0, 2)
+ std %f4, [%o2 + 0x00]
+ std %f6, [%o2 + 0x08]
+11: retl
+ nop
+ENDPROC(aes_sparc64_ecb_decrypt_256)
+
+ .align 32
+ENTRY(aes_sparc64_cbc_encrypt_128)
+ /* %o0=key, %o1=input, %o2=output, %o3=len, %o4=IV */
+ ldd [%o4 + 0x00], %f4
+ ldd [%o4 + 0x08], %f6
+ ldx [%o0 + 0x00], %g1
+ ldx [%o0 + 0x08], %g2
+1: ldx [%o1 + 0x00], %g3
+ ldx [%o1 + 0x08], %g7
+ add %o1, 0x10, %o1
+ xor %g1, %g3, %g3
+ xor %g2, %g7, %g7
+ MOVXTOD_G3_F0
+ MOVXTOD_G7_F2
+ fxor %f4, %f0, %f4
+ fxor %f6, %f2, %f6
+ ENCRYPT_128(8, 4, 6, 0, 2)
+ std %f4, [%o2 + 0x00]
+ std %f6, [%o2 + 0x08]
+ subcc %o3, 0x10, %o3
+ bne,pt %xcc, 1b
+ add %o2, 0x10, %o2
+ std %f4, [%o4 + 0x00]
+ std %f6, [%o4 + 0x08]
+ retl
+ nop
+ENDPROC(aes_sparc64_cbc_encrypt_128)
+
+ .align 32
+ENTRY(aes_sparc64_cbc_encrypt_192)
+ /* %o0=key, %o1=input, %o2=output, %o3=len, %o4=IV */
+ ldd [%o4 + 0x00], %f4
+ ldd [%o4 + 0x08], %f6
+ ldx [%o0 + 0x00], %g1
+ ldx [%o0 + 0x08], %g2
+1: ldx [%o1 + 0x00], %g3
+ ldx [%o1 + 0x08], %g7
+ add %o1, 0x10, %o1
+ xor %g1, %g3, %g3
+ xor %g2, %g7, %g7
+ MOVXTOD_G3_F0
+ MOVXTOD_G7_F2
+ fxor %f4, %f0, %f4
+ fxor %f6, %f2, %f6
+ ENCRYPT_192(8, 4, 6, 0, 2)
+ std %f4, [%o2 + 0x00]
+ std %f6, [%o2 + 0x08]
+ subcc %o3, 0x10, %o3
+ bne,pt %xcc, 1b
+ add %o2, 0x10, %o2
+ std %f4, [%o4 + 0x00]
+ std %f6, [%o4 + 0x08]
+ retl
+ nop
+ENDPROC(aes_sparc64_cbc_encrypt_192)
+
+ .align 32
+ENTRY(aes_sparc64_cbc_encrypt_256)
+ /* %o0=key, %o1=input, %o2=output, %o3=len, %o4=IV */
+ ldd [%o4 + 0x00], %f4
+ ldd [%o4 + 0x08], %f6
+ ldx [%o0 + 0x00], %g1
+ ldx [%o0 + 0x08], %g2
+1: ldx [%o1 + 0x00], %g3
+ ldx [%o1 + 0x08], %g7
+ add %o1, 0x10, %o1
+ xor %g1, %g3, %g3
+ xor %g2, %g7, %g7
+ MOVXTOD_G3_F0
+ MOVXTOD_G7_F2
+ fxor %f4, %f0, %f4
+ fxor %f6, %f2, %f6
+ ENCRYPT_256(8, 4, 6, 0, 2)
+ std %f4, [%o2 + 0x00]
+ std %f6, [%o2 + 0x08]
+ subcc %o3, 0x10, %o3
+ bne,pt %xcc, 1b
+ add %o2, 0x10, %o2
+ std %f4, [%o4 + 0x00]
+ std %f6, [%o4 + 0x08]
+ retl
+ nop
+ENDPROC(aes_sparc64_cbc_encrypt_256)
+
+ .align 32
+ENTRY(aes_sparc64_cbc_decrypt_128)
+ /* %o0=&key[key_len], %o1=input, %o2=output, %o3=len, %o4=iv */
+ ldx [%o0 - 0x10], %g1
+ ldx [%o0 - 0x08], %g2
+ ldx [%o4 + 0x00], %o0
+ ldx [%o4 + 0x08], %o5
+1: ldx [%o1 + 0x00], %g3
+ ldx [%o1 + 0x08], %g7
+ add %o1, 0x10, %o1
+ xor %g1, %g3, %g3
+ xor %g2, %g7, %g7
+ MOVXTOD_G3_F4
+ MOVXTOD_G7_F6
+ DECRYPT_128(8, 4, 6, 0, 2)
+ MOVXTOD_O0_F0
+ MOVXTOD_O5_F2
+ xor %g1, %g3, %o0
+ xor %g2, %g7, %o5
+ fxor %f4, %f0, %f4
+ fxor %f6, %f2, %f6
+ std %f4, [%o2 + 0x00]
+ std %f6, [%o2 + 0x08]
+ subcc %o3, 0x10, %o3
+ bne,pt %xcc, 1b
+ add %o2, 0x10, %o2
+ stx %o0, [%o4 + 0x00]
+ stx %o5, [%o4 + 0x08]
+ retl
+ nop
+ENDPROC(aes_sparc64_cbc_decrypt_128)
+
+ .align 32
+ENTRY(aes_sparc64_cbc_decrypt_192)
+ /* %o0=&key[key_len], %o1=input, %o2=output, %o3=len, %o4=iv */
+ ldx [%o0 - 0x10], %g1
+ ldx [%o0 - 0x08], %g2
+ ldx [%o4 + 0x00], %o0
+ ldx [%o4 + 0x08], %o5
+1: ldx [%o1 + 0x00], %g3
+ ldx [%o1 + 0x08], %g7
+ add %o1, 0x10, %o1
+ xor %g1, %g3, %g3
+ xor %g2, %g7, %g7
+ MOVXTOD_G3_F4
+ MOVXTOD_G7_F6
+ DECRYPT_192(8, 4, 6, 0, 2)
+ MOVXTOD_O0_F0
+ MOVXTOD_O5_F2
+ xor %g1, %g3, %o0
+ xor %g2, %g7, %o5
+ fxor %f4, %f0, %f4
+ fxor %f6, %f2, %f6
+ std %f4, [%o2 + 0x00]
+ std %f6, [%o2 + 0x08]
+ subcc %o3, 0x10, %o3
+ bne,pt %xcc, 1b
+ add %o2, 0x10, %o2
+ stx %o0, [%o4 + 0x00]
+ stx %o5, [%o4 + 0x08]
+ retl
+ nop
+ENDPROC(aes_sparc64_cbc_decrypt_192)
+
+ .align 32
+ENTRY(aes_sparc64_cbc_decrypt_256)
+ /* %o0=&key[key_len], %o1=input, %o2=output, %o3=len, %o4=iv */
+ ldx [%o0 - 0x10], %g1
+ ldx [%o0 - 0x08], %g2
+ ldx [%o4 + 0x00], %o0
+ ldx [%o4 + 0x08], %o5
+1: ldx [%o1 + 0x00], %g3
+ ldx [%o1 + 0x08], %g7
+ add %o1, 0x10, %o1
+ xor %g1, %g3, %g3
+ xor %g2, %g7, %g7
+ MOVXTOD_G3_F4
+ MOVXTOD_G7_F6
+ DECRYPT_256(8, 4, 6, 0, 2)
+ MOVXTOD_O0_F0
+ MOVXTOD_O5_F2
+ xor %g1, %g3, %o0
+ xor %g2, %g7, %o5
+ fxor %f4, %f0, %f4
+ fxor %f6, %f2, %f6
+ std %f4, [%o2 + 0x00]
+ std %f6, [%o2 + 0x08]
+ subcc %o3, 0x10, %o3
+ bne,pt %xcc, 1b
+ add %o2, 0x10, %o2
+ stx %o0, [%o4 + 0x00]
+ stx %o5, [%o4 + 0x08]
+ retl
+ nop
+ENDPROC(aes_sparc64_cbc_decrypt_256)
+
+ .align 32
+ENTRY(aes_sparc64_ctr_crypt_128)
+ /* %o0=key, %o1=input, %o2=output, %o3=len, %o4=IV */
+ ldx [%o4 + 0x00], %g3
+ ldx [%o4 + 0x08], %g7
+ subcc %o3, 0x10, %o3
+ ldx [%o0 + 0x00], %g1
+ be 10f
+ ldx [%o0 + 0x08], %g2
+1: xor %g1, %g3, %o5
+ MOVXTOD_O5_F0
+ xor %g2, %g7, %o5
+ MOVXTOD_O5_F2
+ add %g7, 1, %g7
+ add %g3, 1, %o5
+ movrz %g7, %o5, %g3
+ xor %g1, %g3, %o5
+ MOVXTOD_O5_F4
+ xor %g2, %g7, %o5
+ MOVXTOD_O5_F6
+ add %g7, 1, %g7
+ add %g3, 1, %o5
+ movrz %g7, %o5, %g3
+ ENCRYPT_128_2(8, 0, 2, 4, 6, 56, 58, 60, 62)
+ ldd [%o1 + 0x00], %f56
+ ldd [%o1 + 0x08], %f58
+ ldd [%o1 + 0x10], %f60
+ ldd [%o1 + 0x18], %f62
+ fxor %f56, %f0, %f56
+ fxor %f58, %f2, %f58
+ fxor %f60, %f4, %f60
+ fxor %f62, %f6, %f62
+ std %f56, [%o2 + 0x00]
+ std %f58, [%o2 + 0x08]
+ std %f60, [%o2 + 0x10]
+ std %f62, [%o2 + 0x18]
+ subcc %o3, 0x20, %o3
+ add %o1, 0x20, %o1
+ brgz %o3, 1b
+ add %o2, 0x20, %o2
+ brlz,pt %o3, 11f
+ nop
+10: xor %g1, %g3, %o5
+ MOVXTOD_O5_F0
+ xor %g2, %g7, %o5
+ MOVXTOD_O5_F2
+ add %g7, 1, %g7
+ add %g3, 1, %o5
+ movrz %g7, %o5, %g3
+ ENCRYPT_128(8, 0, 2, 4, 6)
+ ldd [%o1 + 0x00], %f4
+ ldd [%o1 + 0x08], %f6
+ fxor %f4, %f0, %f4
+ fxor %f6, %f2, %f6
+ std %f4, [%o2 + 0x00]
+ std %f6, [%o2 + 0x08]
+11: stx %g3, [%o4 + 0x00]
+ retl
+ stx %g7, [%o4 + 0x08]
+ENDPROC(aes_sparc64_ctr_crypt_128)
+
+ .align 32
+ENTRY(aes_sparc64_ctr_crypt_192)
+ /* %o0=key, %o1=input, %o2=output, %o3=len, %o4=IV */
+ ldx [%o4 + 0x00], %g3
+ ldx [%o4 + 0x08], %g7
+ subcc %o3, 0x10, %o3
+ ldx [%o0 + 0x00], %g1
+ be 10f
+ ldx [%o0 + 0x08], %g2
+1: xor %g1, %g3, %o5
+ MOVXTOD_O5_F0
+ xor %g2, %g7, %o5
+ MOVXTOD_O5_F2
+ add %g7, 1, %g7
+ add %g3, 1, %o5
+ movrz %g7, %o5, %g3
+ xor %g1, %g3, %o5
+ MOVXTOD_O5_F4
+ xor %g2, %g7, %o5
+ MOVXTOD_O5_F6
+ add %g7, 1, %g7
+ add %g3, 1, %o5
+ movrz %g7, %o5, %g3
+ ENCRYPT_192_2(8, 0, 2, 4, 6, 56, 58, 60, 62)
+ ldd [%o1 + 0x00], %f56
+ ldd [%o1 + 0x08], %f58
+ ldd [%o1 + 0x10], %f60
+ ldd [%o1 + 0x18], %f62
+ fxor %f56, %f0, %f56
+ fxor %f58, %f2, %f58
+ fxor %f60, %f4, %f60
+ fxor %f62, %f6, %f62
+ std %f56, [%o2 + 0x00]
+ std %f58, [%o2 + 0x08]
+ std %f60, [%o2 + 0x10]
+ std %f62, [%o2 + 0x18]
+ subcc %o3, 0x20, %o3
+ add %o1, 0x20, %o1
+ brgz %o3, 1b
+ add %o2, 0x20, %o2
+ brlz,pt %o3, 11f
+ nop
+10: xor %g1, %g3, %o5
+ MOVXTOD_O5_F0
+ xor %g2, %g7, %o5
+ MOVXTOD_O5_F2
+ add %g7, 1, %g7
+ add %g3, 1, %o5
+ movrz %g7, %o5, %g3
+ ENCRYPT_192(8, 0, 2, 4, 6)
+ ldd [%o1 + 0x00], %f4
+ ldd [%o1 + 0x08], %f6
+ fxor %f4, %f0, %f4
+ fxor %f6, %f2, %f6
+ std %f4, [%o2 + 0x00]
+ std %f6, [%o2 + 0x08]
+11: stx %g3, [%o4 + 0x00]
+ retl
+ stx %g7, [%o4 + 0x08]
+ENDPROC(aes_sparc64_ctr_crypt_192)
+
+ .align 32
+ENTRY(aes_sparc64_ctr_crypt_256)
+ /* %o0=key, %o1=input, %o2=output, %o3=len, %o4=IV */
+ ldx [%o4 + 0x00], %g3
+ ldx [%o4 + 0x08], %g7
+ subcc %o3, 0x10, %o3
+ ldx [%o0 + 0x00], %g1
+ be 10f
+ ldx [%o0 + 0x08], %g2
+1: xor %g1, %g3, %o5
+ MOVXTOD_O5_F0
+ xor %g2, %g7, %o5
+ MOVXTOD_O5_F2
+ add %g7, 1, %g7
+ add %g3, 1, %o5
+ movrz %g7, %o5, %g3
+ xor %g1, %g3, %o5
+ MOVXTOD_O5_F4
+ xor %g2, %g7, %o5
+ MOVXTOD_O5_F6
+ add %g7, 1, %g7
+ add %g3, 1, %o5
+ movrz %g7, %o5, %g3
+ ENCRYPT_256_2(8, 0, 2, 4, 6)
+ ldd [%o1 + 0x00], %f56
+ ldd [%o1 + 0x08], %f58
+ ldd [%o1 + 0x10], %f60
+ ldd [%o1 + 0x18], %f62
+ fxor %f56, %f0, %f56
+ fxor %f58, %f2, %f58
+ fxor %f60, %f4, %f60
+ fxor %f62, %f6, %f62
+ std %f56, [%o2 + 0x00]
+ std %f58, [%o2 + 0x08]
+ std %f60, [%o2 + 0x10]
+ std %f62, [%o2 + 0x18]
+ subcc %o3, 0x20, %o3
+ add %o1, 0x20, %o1
+ brgz %o3, 1b
+ add %o2, 0x20, %o2
+ brlz,pt %o3, 11f
+ nop
+10: ldd [%o0 + 0xd0], %f56
+ ldd [%o0 + 0xd8], %f58
+ ldd [%o0 + 0xe0], %f60
+ ldd [%o0 + 0xe8], %f62
+ xor %g1, %g3, %o5
+ MOVXTOD_O5_F0
+ xor %g2, %g7, %o5
+ MOVXTOD_O5_F2
+ add %g7, 1, %g7
+ add %g3, 1, %o5
+ movrz %g7, %o5, %g3
+ ENCRYPT_256(8, 0, 2, 4, 6)
+ ldd [%o1 + 0x00], %f4
+ ldd [%o1 + 0x08], %f6
+ fxor %f4, %f0, %f4
+ fxor %f6, %f2, %f6
+ std %f4, [%o2 + 0x00]
+ std %f6, [%o2 + 0x08]
+11: stx %g3, [%o4 + 0x00]
+ retl
+ stx %g7, [%o4 + 0x08]
+ENDPROC(aes_sparc64_ctr_crypt_256)
diff --git a/arch/sparc/crypto/aes_glue.c b/arch/sparc/crypto/aes_glue.c
new file mode 100644
index 00000000000..df922f52d76
--- /dev/null
+++ b/arch/sparc/crypto/aes_glue.c
@@ -0,0 +1,504 @@
+/* Glue code for AES encryption optimized for sparc64 crypto opcodes.
+ *
+ * This is based largely upon arch/x86/crypto/aesni-intel_glue.c
+ *
+ * Copyright (C) 2008, Intel Corp.
+ * Author: Huang Ying <ying.huang@intel.com>
+ *
+ * Added RFC4106 AES-GCM support for 128-bit keys under the AEAD
+ * interface for 64-bit kernels.
+ * Authors: Adrian Hoban <adrian.hoban@intel.com>
+ * Gabriele Paoloni <gabriele.paoloni@intel.com>
+ * Tadeusz Struk (tadeusz.struk@intel.com)
+ * Aidan O'Mahony (aidan.o.mahony@intel.com)
+ * Copyright (c) 2010, Intel Corporation.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/crypto.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/types.h>
+#include <crypto/algapi.h>
+#include <crypto/aes.h>
+
+#include <asm/fpumacro.h>
+#include <asm/pstate.h>
+#include <asm/elf.h>
+
+#include "opcodes.h"
+
+struct aes_ops {
+ void (*encrypt)(const u64 *key, const u32 *input, u32 *output);
+ void (*decrypt)(const u64 *key, const u32 *input, u32 *output);
+ void (*load_encrypt_keys)(const u64 *key);
+ void (*load_decrypt_keys)(const u64 *key);
+ void (*ecb_encrypt)(const u64 *key, const u64 *input, u64 *output,
+ unsigned int len);
+ void (*ecb_decrypt)(const u64 *key, const u64 *input, u64 *output,
+ unsigned int len);
+ void (*cbc_encrypt)(const u64 *key, const u64 *input, u64 *output,
+ unsigned int len, u64 *iv);
+ void (*cbc_decrypt)(const u64 *key, const u64 *input, u64 *output,
+ unsigned int len, u64 *iv);
+ void (*ctr_crypt)(const u64 *key, const u64 *input, u64 *output,
+ unsigned int len, u64 *iv);
+};
+
+struct crypto_sparc64_aes_ctx {
+ struct aes_ops *ops;
+ u64 key[AES_MAX_KEYLENGTH / sizeof(u64)];
+ u32 key_length;
+ u32 expanded_key_length;
+};
+
+extern void aes_sparc64_encrypt_128(const u64 *key, const u32 *input,
+ u32 *output);
+extern void aes_sparc64_encrypt_192(const u64 *key, const u32 *input,
+ u32 *output);
+extern void aes_sparc64_encrypt_256(const u64 *key, const u32 *input,
+ u32 *output);
+
+extern void aes_sparc64_decrypt_128(const u64 *key, const u32 *input,
+ u32 *output);
+extern void aes_sparc64_decrypt_192(const u64 *key, const u32 *input,
+ u32 *output);
+extern void aes_sparc64_decrypt_256(const u64 *key, const u32 *input,
+ u32 *output);
+
+extern void aes_sparc64_load_encrypt_keys_128(const u64 *key);
+extern void aes_sparc64_load_encrypt_keys_192(const u64 *key);
+extern void aes_sparc64_load_encrypt_keys_256(const u64 *key);
+
+extern void aes_sparc64_load_decrypt_keys_128(const u64 *key);
+extern void aes_sparc64_load_decrypt_keys_192(const u64 *key);
+extern void aes_sparc64_load_decrypt_keys_256(const u64 *key);
+
+extern void aes_sparc64_ecb_encrypt_128(const u64 *key, const u64 *input,
+ u64 *output, unsigned int len);
+extern void aes_sparc64_ecb_encrypt_192(const u64 *key, const u64 *input,
+ u64 *output, unsigned int len);
+extern void aes_sparc64_ecb_encrypt_256(const u64 *key, const u64 *input,
+ u64 *output, unsigned int len);
+
+extern void aes_sparc64_ecb_decrypt_128(const u64 *key, const u64 *input,
+ u64 *output, unsigned int len);
+extern void aes_sparc64_ecb_decrypt_192(const u64 *key, const u64 *input,
+ u64 *output, unsigned int len);
+extern void aes_sparc64_ecb_decrypt_256(const u64 *key, const u64 *input,
+ u64 *output, unsigned int len);
+
+extern void aes_sparc64_cbc_encrypt_128(const u64 *key, const u64 *input,
+ u64 *output, unsigned int len,
+ u64 *iv);
+
+extern void aes_sparc64_cbc_encrypt_192(const u64 *key, const u64 *input,
+ u64 *output, unsigned int len,
+ u64 *iv);
+
+extern void aes_sparc64_cbc_encrypt_256(const u64 *key, const u64 *input,
+ u64 *output, unsigned int len,
+ u64 *iv);
+
+extern void aes_sparc64_cbc_decrypt_128(const u64 *key, const u64 *input,
+ u64 *output, unsigned int len,
+ u64 *iv);
+
+extern void aes_sparc64_cbc_decrypt_192(const u64 *key, const u64 *input,
+ u64 *output, unsigned int len,
+ u64 *iv);
+
+extern void aes_sparc64_cbc_decrypt_256(const u64 *key, const u64 *input,
+ u64 *output, unsigned int len,
+ u64 *iv);
+
+extern void aes_sparc64_ctr_crypt_128(const u64 *key, const u64 *input,
+ u64 *output, unsigned int len,
+ u64 *iv);
+extern void aes_sparc64_ctr_crypt_192(const u64 *key, const u64 *input,
+ u64 *output, unsigned int len,
+ u64 *iv);
+extern void aes_sparc64_ctr_crypt_256(const u64 *key, const u64 *input,
+ u64 *output, unsigned int len,
+ u64 *iv);
+
+static struct aes_ops aes128_ops = {
+ .encrypt = aes_sparc64_encrypt_128,
+ .decrypt = aes_sparc64_decrypt_128,
+ .load_encrypt_keys = aes_sparc64_load_encrypt_keys_128,
+ .load_decrypt_keys = aes_sparc64_load_decrypt_keys_128,
+ .ecb_encrypt = aes_sparc64_ecb_encrypt_128,
+ .ecb_decrypt = aes_sparc64_ecb_decrypt_128,
+ .cbc_encrypt = aes_sparc64_cbc_encrypt_128,
+ .cbc_decrypt = aes_sparc64_cbc_decrypt_128,
+ .ctr_crypt = aes_sparc64_ctr_crypt_128,
+};
+
+static struct aes_ops aes192_ops = {
+ .encrypt = aes_sparc64_encrypt_192,
+ .decrypt = aes_sparc64_decrypt_192,
+ .load_encrypt_keys = aes_sparc64_load_encrypt_keys_192,
+ .load_decrypt_keys = aes_sparc64_load_decrypt_keys_192,
+ .ecb_encrypt = aes_sparc64_ecb_encrypt_192,
+ .ecb_decrypt = aes_sparc64_ecb_decrypt_192,
+ .cbc_encrypt = aes_sparc64_cbc_encrypt_192,
+ .cbc_decrypt = aes_sparc64_cbc_decrypt_192,
+ .ctr_crypt = aes_sparc64_ctr_crypt_192,
+};
+
+static struct aes_ops aes256_ops = {
+ .encrypt = aes_sparc64_encrypt_256,
+ .decrypt = aes_sparc64_decrypt_256,
+ .load_encrypt_keys = aes_sparc64_load_encrypt_keys_256,
+ .load_decrypt_keys = aes_sparc64_load_decrypt_keys_256,
+ .ecb_encrypt = aes_sparc64_ecb_encrypt_256,
+ .ecb_decrypt = aes_sparc64_ecb_decrypt_256,
+ .cbc_encrypt = aes_sparc64_cbc_encrypt_256,
+ .cbc_decrypt = aes_sparc64_cbc_decrypt_256,
+ .ctr_crypt = aes_sparc64_ctr_crypt_256,
+};
+
+extern void aes_sparc64_key_expand(const u32 *in_key, u64 *output_key,
+ unsigned int key_len);
+
+static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+ unsigned int key_len)
+{
+ struct crypto_sparc64_aes_ctx *ctx = crypto_tfm_ctx(tfm);
+ u32 *flags = &tfm->crt_flags;
+
+ switch (key_len) {
+ case AES_KEYSIZE_128:
+ ctx->expanded_key_length = 0xb0;
+ ctx->ops = &aes128_ops;
+ break;
+
+ case AES_KEYSIZE_192:
+ ctx->expanded_key_length = 0xd0;
+ ctx->ops = &aes192_ops;
+ break;
+
+ case AES_KEYSIZE_256:
+ ctx->expanded_key_length = 0xf0;
+ ctx->ops = &aes256_ops;
+ break;
+
+ default:
+ *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+ return -EINVAL;
+ }
+
+ aes_sparc64_key_expand((const u32 *)in_key, &ctx->key[0], key_len);
+ ctx->key_length = key_len;
+
+ return 0;
+}
+
+static void aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+ struct crypto_sparc64_aes_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ ctx->ops->encrypt(&ctx->key[0], (const u32 *) src, (u32 *) dst);
+}
+
+static void aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+ struct crypto_sparc64_aes_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ ctx->ops->decrypt(&ctx->key[0], (const u32 *) src, (u32 *) dst);
+}
+
+#define AES_BLOCK_MASK (~(AES_BLOCK_SIZE-1))
+
+static int ecb_encrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ struct crypto_sparc64_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
+ int err;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ err = blkcipher_walk_virt(desc, &walk);
+ desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+
+ ctx->ops->load_encrypt_keys(&ctx->key[0]);
+ while ((nbytes = walk.nbytes)) {
+ unsigned int block_len = nbytes & AES_BLOCK_MASK;
+
+ if (likely(block_len)) {
+ ctx->ops->ecb_encrypt(&ctx->key[0],
+ (const u64 *)walk.src.virt.addr,
+ (u64 *) walk.dst.virt.addr,
+ block_len);
+ }
+ nbytes &= AES_BLOCK_SIZE - 1;
+ err = blkcipher_walk_done(desc, &walk, nbytes);
+ }
+ fprs_write(0);
+ return err;
+}
+
+static int ecb_decrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ struct crypto_sparc64_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
+ u64 *key_end;
+ int err;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ err = blkcipher_walk_virt(desc, &walk);
+ desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+
+ ctx->ops->load_decrypt_keys(&ctx->key[0]);
+ key_end = &ctx->key[ctx->expanded_key_length / sizeof(u64)];
+ while ((nbytes = walk.nbytes)) {
+ unsigned int block_len = nbytes & AES_BLOCK_MASK;
+
+ if (likely(block_len)) {
+ ctx->ops->ecb_decrypt(key_end,
+ (const u64 *) walk.src.virt.addr,
+ (u64 *) walk.dst.virt.addr, block_len);
+ }
+ nbytes &= AES_BLOCK_SIZE - 1;
+ err = blkcipher_walk_done(desc, &walk, nbytes);
+ }
+ fprs_write(0);
+
+ return err;
+}
+
+static int cbc_encrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ struct crypto_sparc64_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
+ int err;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ err = blkcipher_walk_virt(desc, &walk);
+ desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+
+ ctx->ops->load_encrypt_keys(&ctx->key[0]);
+ while ((nbytes = walk.nbytes)) {
+ unsigned int block_len = nbytes & AES_BLOCK_MASK;
+
+ if (likely(block_len)) {
+ ctx->ops->cbc_encrypt(&ctx->key[0],
+ (const u64 *)walk.src.virt.addr,
+ (u64 *) walk.dst.virt.addr,
+ block_len, (u64 *) walk.iv);
+ }
+ nbytes &= AES_BLOCK_SIZE - 1;
+ err = blkcipher_walk_done(desc, &walk, nbytes);
+ }
+ fprs_write(0);
+ return err;
+}
+
+static int cbc_decrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ struct crypto_sparc64_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
+ u64 *key_end;
+ int err;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ err = blkcipher_walk_virt(desc, &walk);
+ desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+
+ ctx->ops->load_decrypt_keys(&ctx->key[0]);
+ key_end = &ctx->key[ctx->expanded_key_length / sizeof(u64)];
+ while ((nbytes = walk.nbytes)) {
+ unsigned int block_len = nbytes & AES_BLOCK_MASK;
+
+ if (likely(block_len)) {
+ ctx->ops->cbc_decrypt(key_end,
+ (const u64 *) walk.src.virt.addr,
+ (u64 *) walk.dst.virt.addr,
+ block_len, (u64 *) walk.iv);
+ }
+ nbytes &= AES_BLOCK_SIZE - 1;
+ err = blkcipher_walk_done(desc, &walk, nbytes);
+ }
+ fprs_write(0);
+
+ return err;
+}
+
+static void ctr_crypt_final(struct crypto_sparc64_aes_ctx *ctx,
+ struct blkcipher_walk *walk)
+{
+ u8 *ctrblk = walk->iv;
+ u64 keystream[AES_BLOCK_SIZE / sizeof(u64)];
+ u8 *src = walk->src.virt.addr;
+ u8 *dst = walk->dst.virt.addr;
+ unsigned int nbytes = walk->nbytes;
+
+ ctx->ops->ecb_encrypt(&ctx->key[0], (const u64 *)ctrblk,
+ keystream, AES_BLOCK_SIZE);
+ crypto_xor((u8 *) keystream, src, nbytes);
+ memcpy(dst, keystream, nbytes);
+ crypto_inc(ctrblk, AES_BLOCK_SIZE);
+}
+
+static int ctr_crypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ struct crypto_sparc64_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
+ int err;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ err = blkcipher_walk_virt_block(desc, &walk, AES_BLOCK_SIZE);
+ desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+
+ ctx->ops->load_encrypt_keys(&ctx->key[0]);
+ while ((nbytes = walk.nbytes) >= AES_BLOCK_SIZE) {
+ unsigned int block_len = nbytes & AES_BLOCK_MASK;
+
+ if (likely(block_len)) {
+ ctx->ops->ctr_crypt(&ctx->key[0],
+ (const u64 *)walk.src.virt.addr,
+ (u64 *) walk.dst.virt.addr,
+ block_len, (u64 *) walk.iv);
+ }
+ nbytes &= AES_BLOCK_SIZE - 1;
+ err = blkcipher_walk_done(desc, &walk, nbytes);
+ }
+ if (walk.nbytes) {
+ ctr_crypt_final(ctx, &walk);
+ err = blkcipher_walk_done(desc, &walk, 0);
+ }
+ fprs_write(0);
+ return err;
+}
+
+static struct crypto_alg algs[] = { {
+ .cra_name = "aes",
+ .cra_driver_name = "aes-sparc64",
+ .cra_priority = SPARC_CR_OPCODE_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct crypto_sparc64_aes_ctx),
+ .cra_alignmask = 3,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .cipher = {
+ .cia_min_keysize = AES_MIN_KEY_SIZE,
+ .cia_max_keysize = AES_MAX_KEY_SIZE,
+ .cia_setkey = aes_set_key,
+ .cia_encrypt = aes_encrypt,
+ .cia_decrypt = aes_decrypt
+ }
+ }
+}, {
+ .cra_name = "ecb(aes)",
+ .cra_driver_name = "ecb-aes-sparc64",
+ .cra_priority = SPARC_CR_OPCODE_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct crypto_sparc64_aes_ctx),
+ .cra_alignmask = 7,
+ .cra_type = &crypto_blkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .blkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .setkey = aes_set_key,
+ .encrypt = ecb_encrypt,
+ .decrypt = ecb_decrypt,
+ },
+ },
+}, {
+ .cra_name = "cbc(aes)",
+ .cra_driver_name = "cbc-aes-sparc64",
+ .cra_priority = SPARC_CR_OPCODE_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct crypto_sparc64_aes_ctx),
+ .cra_alignmask = 7,
+ .cra_type = &crypto_blkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .blkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .setkey = aes_set_key,
+ .encrypt = cbc_encrypt,
+ .decrypt = cbc_decrypt,
+ },
+ },
+}, {
+ .cra_name = "ctr(aes)",
+ .cra_driver_name = "ctr-aes-sparc64",
+ .cra_priority = SPARC_CR_OPCODE_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_blocksize = 1,
+ .cra_ctxsize = sizeof(struct crypto_sparc64_aes_ctx),
+ .cra_alignmask = 7,
+ .cra_type = &crypto_blkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .blkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .setkey = aes_set_key,
+ .encrypt = ctr_crypt,
+ .decrypt = ctr_crypt,
+ },
+ },
+} };
+
+static bool __init sparc64_has_aes_opcode(void)
+{
+ unsigned long cfr;
+
+ if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO))
+ return false;
+
+ __asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr));
+ if (!(cfr & CFR_AES))
+ return false;
+
+ return true;
+}
+
+static int __init aes_sparc64_mod_init(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(algs); i++)
+ INIT_LIST_HEAD(&algs[i].cra_list);
+
+ if (sparc64_has_aes_opcode()) {
+ pr_info("Using sparc64 aes opcodes optimized AES implementation\n");
+ return crypto_register_algs(algs, ARRAY_SIZE(algs));
+ }
+ pr_info("sparc64 aes opcodes not available.\n");
+ return -ENODEV;
+}
+
+static void __exit aes_sparc64_mod_fini(void)
+{
+ crypto_unregister_algs(algs, ARRAY_SIZE(algs));
+}
+
+module_init(aes_sparc64_mod_init);
+module_exit(aes_sparc64_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("AES Secure Hash Algorithm, sparc64 aes opcode accelerated");
+
+MODULE_ALIAS("aes");
+
+#include "crop_devid.c"
diff --git a/arch/sparc/crypto/camellia_asm.S b/arch/sparc/crypto/camellia_asm.S
new file mode 100644
index 00000000000..cc39553a4e4
--- /dev/null
+++ b/arch/sparc/crypto/camellia_asm.S
@@ -0,0 +1,563 @@
+#include <linux/linkage.h>
+#include <asm/visasm.h>
+
+#include "opcodes.h"
+
+#define CAMELLIA_6ROUNDS(KEY_BASE, I0, I1) \
+ CAMELLIA_F(KEY_BASE + 0, I1, I0, I1) \
+ CAMELLIA_F(KEY_BASE + 2, I0, I1, I0) \
+ CAMELLIA_F(KEY_BASE + 4, I1, I0, I1) \
+ CAMELLIA_F(KEY_BASE + 6, I0, I1, I0) \
+ CAMELLIA_F(KEY_BASE + 8, I1, I0, I1) \
+ CAMELLIA_F(KEY_BASE + 10, I0, I1, I0)
+
+#define CAMELLIA_6ROUNDS_FL_FLI(KEY_BASE, I0, I1) \
+ CAMELLIA_6ROUNDS(KEY_BASE, I0, I1) \
+ CAMELLIA_FL(KEY_BASE + 12, I0, I0) \
+ CAMELLIA_FLI(KEY_BASE + 14, I1, I1)
+
+ .data
+
+ .align 8
+SIGMA: .xword 0xA09E667F3BCC908B
+ .xword 0xB67AE8584CAA73B2
+ .xword 0xC6EF372FE94F82BE
+ .xword 0x54FF53A5F1D36F1C
+ .xword 0x10E527FADE682D1D
+ .xword 0xB05688C2B3E6C1FD
+
+ .text
+
+ .align 32
+ENTRY(camellia_sparc64_key_expand)
+ /* %o0=in_key, %o1=encrypt_key, %o2=key_len, %o3=decrypt_key */
+ VISEntry
+ ld [%o0 + 0x00], %f0 ! i0, k[0]
+ ld [%o0 + 0x04], %f1 ! i1, k[1]
+ ld [%o0 + 0x08], %f2 ! i2, k[2]
+ ld [%o0 + 0x0c], %f3 ! i3, k[3]
+ std %f0, [%o1 + 0x00] ! k[0, 1]
+ fsrc2 %f0, %f28
+ std %f2, [%o1 + 0x08] ! k[2, 3]
+ cmp %o2, 16
+ be 10f
+ fsrc2 %f2, %f30
+
+ ld [%o0 + 0x10], %f0
+ ld [%o0 + 0x14], %f1
+ std %f0, [%o1 + 0x20] ! k[8, 9]
+ cmp %o2, 24
+ fone %f10
+ be,a 1f
+ fxor %f10, %f0, %f2
+ ld [%o0 + 0x18], %f2
+ ld [%o0 + 0x1c], %f3
+1:
+ std %f2, [%o1 + 0x28] ! k[10, 11]
+ fxor %f28, %f0, %f0
+ fxor %f30, %f2, %f2
+
+10:
+ sethi %hi(SIGMA), %g3
+ or %g3, %lo(SIGMA), %g3
+ ldd [%g3 + 0x00], %f16
+ ldd [%g3 + 0x08], %f18
+ ldd [%g3 + 0x10], %f20
+ ldd [%g3 + 0x18], %f22
+ ldd [%g3 + 0x20], %f24
+ ldd [%g3 + 0x28], %f26
+ CAMELLIA_F(16, 2, 0, 2)
+ CAMELLIA_F(18, 0, 2, 0)
+ fxor %f28, %f0, %f0
+ fxor %f30, %f2, %f2
+ CAMELLIA_F(20, 2, 0, 2)
+ CAMELLIA_F(22, 0, 2, 0)
+
+#define ROTL128(S01, S23, TMP1, TMP2, N) \
+ srlx S01, (64 - N), TMP1; \
+ sllx S01, N, S01; \
+ srlx S23, (64 - N), TMP2; \
+ sllx S23, N, S23; \
+ or S01, TMP2, S01; \
+ or S23, TMP1, S23
+
+ cmp %o2, 16
+ bne 1f
+ nop
+ /* 128-bit key */
+ std %f0, [%o1 + 0x10] ! k[ 4, 5]
+ std %f2, [%o1 + 0x18] ! k[ 6, 7]
+ MOVDTOX_F0_O4
+ MOVDTOX_F2_O5
+ ROTL128(%o4, %o5, %g2, %g3, 15)
+ stx %o4, [%o1 + 0x30] ! k[12, 13]
+ stx %o5, [%o1 + 0x38] ! k[14, 15]
+ ROTL128(%o4, %o5, %g2, %g3, 15)
+ stx %o4, [%o1 + 0x40] ! k[16, 17]
+ stx %o5, [%o1 + 0x48] ! k[18, 19]
+ ROTL128(%o4, %o5, %g2, %g3, 15)
+ stx %o4, [%o1 + 0x60] ! k[24, 25]
+ ROTL128(%o4, %o5, %g2, %g3, 15)
+ stx %o4, [%o1 + 0x70] ! k[28, 29]
+ stx %o5, [%o1 + 0x78] ! k[30, 31]
+ ROTL128(%o4, %o5, %g2, %g3, 34)
+ stx %o4, [%o1 + 0xa0] ! k[40, 41]
+ stx %o5, [%o1 + 0xa8] ! k[42, 43]
+ ROTL128(%o4, %o5, %g2, %g3, 17)
+ stx %o4, [%o1 + 0xc0] ! k[48, 49]
+ stx %o5, [%o1 + 0xc8] ! k[50, 51]
+
+ ldx [%o1 + 0x00], %o4 ! k[ 0, 1]
+ ldx [%o1 + 0x08], %o5 ! k[ 2, 3]
+ ROTL128(%o4, %o5, %g2, %g3, 15)
+ stx %o4, [%o1 + 0x20] ! k[ 8, 9]
+ stx %o5, [%o1 + 0x28] ! k[10, 11]
+ ROTL128(%o4, %o5, %g2, %g3, 30)
+ stx %o4, [%o1 + 0x50] ! k[20, 21]
+ stx %o5, [%o1 + 0x58] ! k[22, 23]
+ ROTL128(%o4, %o5, %g2, %g3, 15)
+ stx %o5, [%o1 + 0x68] ! k[26, 27]
+ ROTL128(%o4, %o5, %g2, %g3, 17)
+ stx %o4, [%o1 + 0x80] ! k[32, 33]
+ stx %o5, [%o1 + 0x88] ! k[34, 35]
+ ROTL128(%o4, %o5, %g2, %g3, 17)
+ stx %o4, [%o1 + 0x90] ! k[36, 37]
+ stx %o5, [%o1 + 0x98] ! k[38, 39]
+ ROTL128(%o4, %o5, %g2, %g3, 17)
+ stx %o4, [%o1 + 0xb0] ! k[44, 45]
+ stx %o5, [%o1 + 0xb8] ! k[46, 47]
+
+ ba,pt %xcc, 2f
+ mov (3 * 16 * 4), %o0
+
+1:
+ /* 192-bit or 256-bit key */
+ std %f0, [%o1 + 0x30] ! k[12, 13]
+ std %f2, [%o1 + 0x38] ! k[14, 15]
+ ldd [%o1 + 0x20], %f4 ! k[ 8, 9]
+ ldd [%o1 + 0x28], %f6 ! k[10, 11]
+ fxor %f0, %f4, %f0
+ fxor %f2, %f6, %f2
+ CAMELLIA_F(24, 2, 0, 2)
+ CAMELLIA_F(26, 0, 2, 0)
+ std %f0, [%o1 + 0x10] ! k[ 4, 5]
+ std %f2, [%o1 + 0x18] ! k[ 6, 7]
+ MOVDTOX_F0_O4
+ MOVDTOX_F2_O5
+ ROTL128(%o4, %o5, %g2, %g3, 30)
+ stx %o4, [%o1 + 0x50] ! k[20, 21]
+ stx %o5, [%o1 + 0x58] ! k[22, 23]
+ ROTL128(%o4, %o5, %g2, %g3, 30)
+ stx %o4, [%o1 + 0xa0] ! k[40, 41]
+ stx %o5, [%o1 + 0xa8] ! k[42, 43]
+ ROTL128(%o4, %o5, %g2, %g3, 51)
+ stx %o4, [%o1 + 0x100] ! k[64, 65]
+ stx %o5, [%o1 + 0x108] ! k[66, 67]
+ ldx [%o1 + 0x20], %o4 ! k[ 8, 9]
+ ldx [%o1 + 0x28], %o5 ! k[10, 11]
+ ROTL128(%o4, %o5, %g2, %g3, 15)
+ stx %o4, [%o1 + 0x20] ! k[ 8, 9]
+ stx %o5, [%o1 + 0x28] ! k[10, 11]
+ ROTL128(%o4, %o5, %g2, %g3, 15)
+ stx %o4, [%o1 + 0x40] ! k[16, 17]
+ stx %o5, [%o1 + 0x48] ! k[18, 19]
+ ROTL128(%o4, %o5, %g2, %g3, 30)
+ stx %o4, [%o1 + 0x90] ! k[36, 37]
+ stx %o5, [%o1 + 0x98] ! k[38, 39]
+ ROTL128(%o4, %o5, %g2, %g3, 34)
+ stx %o4, [%o1 + 0xd0] ! k[52, 53]
+ stx %o5, [%o1 + 0xd8] ! k[54, 55]
+ ldx [%o1 + 0x30], %o4 ! k[12, 13]
+ ldx [%o1 + 0x38], %o5 ! k[14, 15]
+ ROTL128(%o4, %o5, %g2, %g3, 15)
+ stx %o4, [%o1 + 0x30] ! k[12, 13]
+ stx %o5, [%o1 + 0x38] ! k[14, 15]
+ ROTL128(%o4, %o5, %g2, %g3, 30)
+ stx %o4, [%o1 + 0x70] ! k[28, 29]
+ stx %o5, [%o1 + 0x78] ! k[30, 31]
+ srlx %o4, 32, %g2
+ srlx %o5, 32, %g3
+ stw %o4, [%o1 + 0xc0] ! k[48]
+ stw %g3, [%o1 + 0xc4] ! k[49]
+ stw %o5, [%o1 + 0xc8] ! k[50]
+ stw %g2, [%o1 + 0xcc] ! k[51]
+ ROTL128(%o4, %o5, %g2, %g3, 49)
+ stx %o4, [%o1 + 0xe0] ! k[56, 57]
+ stx %o5, [%o1 + 0xe8] ! k[58, 59]
+ ldx [%o1 + 0x00], %o4 ! k[ 0, 1]
+ ldx [%o1 + 0x08], %o5 ! k[ 2, 3]
+ ROTL128(%o4, %o5, %g2, %g3, 45)
+ stx %o4, [%o1 + 0x60] ! k[24, 25]
+ stx %o5, [%o1 + 0x68] ! k[26, 27]
+ ROTL128(%o4, %o5, %g2, %g3, 15)
+ stx %o4, [%o1 + 0x80] ! k[32, 33]
+ stx %o5, [%o1 + 0x88] ! k[34, 35]
+ ROTL128(%o4, %o5, %g2, %g3, 17)
+ stx %o4, [%o1 + 0xb0] ! k[44, 45]
+ stx %o5, [%o1 + 0xb8] ! k[46, 47]
+ ROTL128(%o4, %o5, %g2, %g3, 34)
+ stx %o4, [%o1 + 0xf0] ! k[60, 61]
+ stx %o5, [%o1 + 0xf8] ! k[62, 63]
+ mov (4 * 16 * 4), %o0
+2:
+ add %o1, %o0, %o1
+ ldd [%o1 + 0x00], %f0
+ ldd [%o1 + 0x08], %f2
+ std %f0, [%o3 + 0x00]
+ std %f2, [%o3 + 0x08]
+ add %o3, 0x10, %o3
+1:
+ sub %o1, (16 * 4), %o1
+ ldd [%o1 + 0x38], %f0
+ ldd [%o1 + 0x30], %f2
+ ldd [%o1 + 0x28], %f4
+ ldd [%o1 + 0x20], %f6
+ ldd [%o1 + 0x18], %f8
+ ldd [%o1 + 0x10], %f10
+ std %f0, [%o3 + 0x00]
+ std %f2, [%o3 + 0x08]
+ std %f4, [%o3 + 0x10]
+ std %f6, [%o3 + 0x18]
+ std %f8, [%o3 + 0x20]
+ std %f10, [%o3 + 0x28]
+
+ ldd [%o1 + 0x08], %f0
+ ldd [%o1 + 0x00], %f2
+ std %f0, [%o3 + 0x30]
+ std %f2, [%o3 + 0x38]
+ subcc %o0, (16 * 4), %o0
+ bne,pt %icc, 1b
+ add %o3, (16 * 4), %o3
+
+ std %f2, [%o3 - 0x10]
+ std %f0, [%o3 - 0x08]
+
+ retl
+ VISExit
+ENDPROC(camellia_sparc64_key_expand)
+
+ .align 32
+ENTRY(camellia_sparc64_crypt)
+ /* %o0=key, %o1=input, %o2=output, %o3=key_len */
+ VISEntry
+
+ ld [%o1 + 0x00], %f0
+ ld [%o1 + 0x04], %f1
+ ld [%o1 + 0x08], %f2
+ ld [%o1 + 0x0c], %f3
+
+ ldd [%o0 + 0x00], %f4
+ ldd [%o0 + 0x08], %f6
+
+ cmp %o3, 16
+ fxor %f4, %f0, %f0
+ be 1f
+ fxor %f6, %f2, %f2
+
+ ldd [%o0 + 0x10], %f8
+ ldd [%o0 + 0x18], %f10
+ ldd [%o0 + 0x20], %f12
+ ldd [%o0 + 0x28], %f14
+ ldd [%o0 + 0x30], %f16
+ ldd [%o0 + 0x38], %f18
+ ldd [%o0 + 0x40], %f20
+ ldd [%o0 + 0x48], %f22
+ add %o0, 0x40, %o0
+
+ CAMELLIA_6ROUNDS_FL_FLI( 8, 0, 2)
+
+1:
+ ldd [%o0 + 0x10], %f8
+ ldd [%o0 + 0x18], %f10
+ ldd [%o0 + 0x20], %f12
+ ldd [%o0 + 0x28], %f14
+ ldd [%o0 + 0x30], %f16
+ ldd [%o0 + 0x38], %f18
+ ldd [%o0 + 0x40], %f20
+ ldd [%o0 + 0x48], %f22
+ ldd [%o0 + 0x50], %f24
+ ldd [%o0 + 0x58], %f26
+ ldd [%o0 + 0x60], %f28
+ ldd [%o0 + 0x68], %f30
+ ldd [%o0 + 0x70], %f32
+ ldd [%o0 + 0x78], %f34
+ ldd [%o0 + 0x80], %f36
+ ldd [%o0 + 0x88], %f38
+ ldd [%o0 + 0x90], %f40
+ ldd [%o0 + 0x98], %f42
+ ldd [%o0 + 0xa0], %f44
+ ldd [%o0 + 0xa8], %f46
+ ldd [%o0 + 0xb0], %f48
+ ldd [%o0 + 0xb8], %f50
+ ldd [%o0 + 0xc0], %f52
+ ldd [%o0 + 0xc8], %f54
+
+ CAMELLIA_6ROUNDS_FL_FLI( 8, 0, 2)
+ CAMELLIA_6ROUNDS_FL_FLI(24, 0, 2)
+ CAMELLIA_6ROUNDS(40, 0, 2)
+ fxor %f52, %f2, %f2
+ fxor %f54, %f0, %f0
+
+ st %f2, [%o2 + 0x00]
+ st %f3, [%o2 + 0x04]
+ st %f0, [%o2 + 0x08]
+ st %f1, [%o2 + 0x0c]
+
+ retl
+ VISExit
+ENDPROC(camellia_sparc64_crypt)
+
+ .align 32
+ENTRY(camellia_sparc64_load_keys)
+ /* %o0=key, %o1=key_len */
+ VISEntry
+ ldd [%o0 + 0x00], %f4
+ ldd [%o0 + 0x08], %f6
+ ldd [%o0 + 0x10], %f8
+ ldd [%o0 + 0x18], %f10
+ ldd [%o0 + 0x20], %f12
+ ldd [%o0 + 0x28], %f14
+ ldd [%o0 + 0x30], %f16
+ ldd [%o0 + 0x38], %f18
+ ldd [%o0 + 0x40], %f20
+ ldd [%o0 + 0x48], %f22
+ ldd [%o0 + 0x50], %f24
+ ldd [%o0 + 0x58], %f26
+ ldd [%o0 + 0x60], %f28
+ ldd [%o0 + 0x68], %f30
+ ldd [%o0 + 0x70], %f32
+ ldd [%o0 + 0x78], %f34
+ ldd [%o0 + 0x80], %f36
+ ldd [%o0 + 0x88], %f38
+ ldd [%o0 + 0x90], %f40
+ ldd [%o0 + 0x98], %f42
+ ldd [%o0 + 0xa0], %f44
+ ldd [%o0 + 0xa8], %f46
+ ldd [%o0 + 0xb0], %f48
+ ldd [%o0 + 0xb8], %f50
+ ldd [%o0 + 0xc0], %f52
+ retl
+ ldd [%o0 + 0xc8], %f54
+ENDPROC(camellia_sparc64_load_keys)
+
+ .align 32
+ENTRY(camellia_sparc64_ecb_crypt_3_grand_rounds)
+ /* %o0=input, %o1=output, %o2=len, %o3=key */
+1: ldd [%o0 + 0x00], %f0
+ ldd [%o0 + 0x08], %f2
+ add %o0, 0x10, %o0
+ fxor %f4, %f0, %f0
+ fxor %f6, %f2, %f2
+ CAMELLIA_6ROUNDS_FL_FLI( 8, 0, 2)
+ CAMELLIA_6ROUNDS_FL_FLI(24, 0, 2)
+ CAMELLIA_6ROUNDS(40, 0, 2)
+ fxor %f52, %f2, %f2
+ fxor %f54, %f0, %f0
+ std %f2, [%o1 + 0x00]
+ std %f0, [%o1 + 0x08]
+ subcc %o2, 0x10, %o2
+ bne,pt %icc, 1b
+ add %o1, 0x10, %o1
+ retl
+ nop
+ENDPROC(camellia_sparc64_ecb_crypt_3_grand_rounds)
+
+ .align 32
+ENTRY(camellia_sparc64_ecb_crypt_4_grand_rounds)
+ /* %o0=input, %o1=output, %o2=len, %o3=key */
+1: ldd [%o0 + 0x00], %f0
+ ldd [%o0 + 0x08], %f2
+ add %o0, 0x10, %o0
+ fxor %f4, %f0, %f0
+ fxor %f6, %f2, %f2
+ CAMELLIA_6ROUNDS_FL_FLI( 8, 0, 2)
+ ldd [%o3 + 0xd0], %f8
+ ldd [%o3 + 0xd8], %f10
+ ldd [%o3 + 0xe0], %f12
+ ldd [%o3 + 0xe8], %f14
+ ldd [%o3 + 0xf0], %f16
+ ldd [%o3 + 0xf8], %f18
+ ldd [%o3 + 0x100], %f20
+ ldd [%o3 + 0x108], %f22
+ CAMELLIA_6ROUNDS_FL_FLI(24, 0, 2)
+ CAMELLIA_6ROUNDS_FL_FLI(40, 0, 2)
+ CAMELLIA_F(8, 2, 0, 2)
+ CAMELLIA_F(10, 0, 2, 0)
+ ldd [%o3 + 0x10], %f8
+ ldd [%o3 + 0x18], %f10
+ CAMELLIA_F(12, 2, 0, 2)
+ CAMELLIA_F(14, 0, 2, 0)
+ ldd [%o3 + 0x20], %f12
+ ldd [%o3 + 0x28], %f14
+ CAMELLIA_F(16, 2, 0, 2)
+ CAMELLIA_F(18, 0, 2, 0)
+ ldd [%o3 + 0x30], %f16
+ ldd [%o3 + 0x38], %f18
+ fxor %f20, %f2, %f2
+ fxor %f22, %f0, %f0
+ ldd [%o3 + 0x40], %f20
+ ldd [%o3 + 0x48], %f22
+ std %f2, [%o1 + 0x00]
+ std %f0, [%o1 + 0x08]
+ subcc %o2, 0x10, %o2
+ bne,pt %icc, 1b
+ add %o1, 0x10, %o1
+ retl
+ nop
+ENDPROC(camellia_sparc64_ecb_crypt_4_grand_rounds)
+
+ .align 32
+ENTRY(camellia_sparc64_cbc_encrypt_3_grand_rounds)
+ /* %o0=input, %o1=output, %o2=len, %o3=key, %o4=IV */
+ ldd [%o4 + 0x00], %f60
+ ldd [%o4 + 0x08], %f62
+1: ldd [%o0 + 0x00], %f0
+ ldd [%o0 + 0x08], %f2
+ add %o0, 0x10, %o0
+ fxor %f60, %f0, %f0
+ fxor %f62, %f2, %f2
+ fxor %f4, %f0, %f0
+ fxor %f6, %f2, %f2
+ CAMELLIA_6ROUNDS_FL_FLI( 8, 0, 2)
+ CAMELLIA_6ROUNDS_FL_FLI(24, 0, 2)
+ CAMELLIA_6ROUNDS(40, 0, 2)
+ fxor %f52, %f2, %f60
+ fxor %f54, %f0, %f62
+ std %f60, [%o1 + 0x00]
+ std %f62, [%o1 + 0x08]
+ subcc %o2, 0x10, %o2
+ bne,pt %icc, 1b
+ add %o1, 0x10, %o1
+ std %f60, [%o4 + 0x00]
+ retl
+ std %f62, [%o4 + 0x08]
+ENDPROC(camellia_sparc64_cbc_encrypt_3_grand_rounds)
+
+ .align 32
+ENTRY(camellia_sparc64_cbc_encrypt_4_grand_rounds)
+ /* %o0=input, %o1=output, %o2=len, %o3=key, %o4=IV */
+ ldd [%o4 + 0x00], %f60
+ ldd [%o4 + 0x08], %f62
+1: ldd [%o0 + 0x00], %f0
+ ldd [%o0 + 0x08], %f2
+ add %o0, 0x10, %o0
+ fxor %f60, %f0, %f0
+ fxor %f62, %f2, %f2
+ fxor %f4, %f0, %f0
+ fxor %f6, %f2, %f2
+ CAMELLIA_6ROUNDS_FL_FLI( 8, 0, 2)
+ ldd [%o3 + 0xd0], %f8
+ ldd [%o3 + 0xd8], %f10
+ ldd [%o3 + 0xe0], %f12
+ ldd [%o3 + 0xe8], %f14
+ ldd [%o3 + 0xf0], %f16
+ ldd [%o3 + 0xf8], %f18
+ ldd [%o3 + 0x100], %f20
+ ldd [%o3 + 0x108], %f22
+ CAMELLIA_6ROUNDS_FL_FLI(24, 0, 2)
+ CAMELLIA_6ROUNDS_FL_FLI(40, 0, 2)
+ CAMELLIA_F(8, 2, 0, 2)
+ CAMELLIA_F(10, 0, 2, 0)
+ ldd [%o3 + 0x10], %f8
+ ldd [%o3 + 0x18], %f10
+ CAMELLIA_F(12, 2, 0, 2)
+ CAMELLIA_F(14, 0, 2, 0)
+ ldd [%o3 + 0x20], %f12
+ ldd [%o3 + 0x28], %f14
+ CAMELLIA_F(16, 2, 0, 2)
+ CAMELLIA_F(18, 0, 2, 0)
+ ldd [%o3 + 0x30], %f16
+ ldd [%o3 + 0x38], %f18
+ fxor %f20, %f2, %f60
+ fxor %f22, %f0, %f62
+ ldd [%o3 + 0x40], %f20
+ ldd [%o3 + 0x48], %f22
+ std %f60, [%o1 + 0x00]
+ std %f62, [%o1 + 0x08]
+ subcc %o2, 0x10, %o2
+ bne,pt %icc, 1b
+ add %o1, 0x10, %o1
+ std %f60, [%o4 + 0x00]
+ retl
+ std %f62, [%o4 + 0x08]
+ENDPROC(camellia_sparc64_cbc_encrypt_4_grand_rounds)
+
+ .align 32
+ENTRY(camellia_sparc64_cbc_decrypt_3_grand_rounds)
+ /* %o0=input, %o1=output, %o2=len, %o3=key, %o4=IV */
+ ldd [%o4 + 0x00], %f60
+ ldd [%o4 + 0x08], %f62
+1: ldd [%o0 + 0x00], %f56
+ ldd [%o0 + 0x08], %f58
+ add %o0, 0x10, %o0
+ fxor %f4, %f56, %f0
+ fxor %f6, %f58, %f2
+ CAMELLIA_6ROUNDS_FL_FLI( 8, 0, 2)
+ CAMELLIA_6ROUNDS_FL_FLI(24, 0, 2)
+ CAMELLIA_6ROUNDS(40, 0, 2)
+ fxor %f52, %f2, %f2
+ fxor %f54, %f0, %f0
+ fxor %f60, %f2, %f2
+ fxor %f62, %f0, %f0
+ fsrc2 %f56, %f60
+ fsrc2 %f58, %f62
+ std %f2, [%o1 + 0x00]
+ std %f0, [%o1 + 0x08]
+ subcc %o2, 0x10, %o2
+ bne,pt %icc, 1b
+ add %o1, 0x10, %o1
+ std %f60, [%o4 + 0x00]
+ retl
+ std %f62, [%o4 + 0x08]
+ENDPROC(camellia_sparc64_cbc_decrypt_3_grand_rounds)
+
+ .align 32
+ENTRY(camellia_sparc64_cbc_decrypt_4_grand_rounds)
+ /* %o0=input, %o1=output, %o2=len, %o3=key, %o4=IV */
+ ldd [%o4 + 0x00], %f60
+ ldd [%o4 + 0x08], %f62
+1: ldd [%o0 + 0x00], %f56
+ ldd [%o0 + 0x08], %f58
+ add %o0, 0x10, %o0
+ fxor %f4, %f56, %f0
+ fxor %f6, %f58, %f2
+ CAMELLIA_6ROUNDS_FL_FLI( 8, 0, 2)
+ ldd [%o3 + 0xd0], %f8
+ ldd [%o3 + 0xd8], %f10
+ ldd [%o3 + 0xe0], %f12
+ ldd [%o3 + 0xe8], %f14
+ ldd [%o3 + 0xf0], %f16
+ ldd [%o3 + 0xf8], %f18
+ ldd [%o3 + 0x100], %f20
+ ldd [%o3 + 0x108], %f22
+ CAMELLIA_6ROUNDS_FL_FLI(24, 0, 2)
+ CAMELLIA_6ROUNDS_FL_FLI(40, 0, 2)
+ CAMELLIA_F(8, 2, 0, 2)
+ CAMELLIA_F(10, 0, 2, 0)
+ ldd [%o3 + 0x10], %f8
+ ldd [%o3 + 0x18], %f10
+ CAMELLIA_F(12, 2, 0, 2)
+ CAMELLIA_F(14, 0, 2, 0)
+ ldd [%o3 + 0x20], %f12
+ ldd [%o3 + 0x28], %f14
+ CAMELLIA_F(16, 2, 0, 2)
+ CAMELLIA_F(18, 0, 2, 0)
+ ldd [%o3 + 0x30], %f16
+ ldd [%o3 + 0x38], %f18
+ fxor %f20, %f2, %f2
+ fxor %f22, %f0, %f0
+ ldd [%o3 + 0x40], %f20
+ ldd [%o3 + 0x48], %f22
+ fxor %f60, %f2, %f2
+ fxor %f62, %f0, %f0
+ fsrc2 %f56, %f60
+ fsrc2 %f58, %f62
+ std %f2, [%o1 + 0x00]
+ std %f0, [%o1 + 0x08]
+ subcc %o2, 0x10, %o2
+ bne,pt %icc, 1b
+ add %o1, 0x10, %o1
+ std %f60, [%o4 + 0x00]
+ retl
+ std %f62, [%o4 + 0x08]
+ENDPROC(camellia_sparc64_cbc_decrypt_4_grand_rounds)
diff --git a/arch/sparc/crypto/camellia_glue.c b/arch/sparc/crypto/camellia_glue.c
new file mode 100644
index 00000000000..888f6260b4e
--- /dev/null
+++ b/arch/sparc/crypto/camellia_glue.c
@@ -0,0 +1,327 @@
+/* Glue code for CAMELLIA encryption optimized for sparc64 crypto opcodes.
+ *
+ * Copyright (C) 2012 David S. Miller <davem@davemloft.net>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/crypto.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/types.h>
+#include <crypto/algapi.h>
+
+#include <asm/fpumacro.h>
+#include <asm/pstate.h>
+#include <asm/elf.h>
+
+#include "opcodes.h"
+
+#define CAMELLIA_MIN_KEY_SIZE 16
+#define CAMELLIA_MAX_KEY_SIZE 32
+#define CAMELLIA_BLOCK_SIZE 16
+#define CAMELLIA_TABLE_BYTE_LEN 272
+
+struct camellia_sparc64_ctx {
+ u64 encrypt_key[CAMELLIA_TABLE_BYTE_LEN / sizeof(u64)];
+ u64 decrypt_key[CAMELLIA_TABLE_BYTE_LEN / sizeof(u64)];
+ int key_len;
+};
+
+extern void camellia_sparc64_key_expand(const u32 *in_key, u64 *encrypt_key,
+ unsigned int key_len, u64 *decrypt_key);
+
+static int camellia_set_key(struct crypto_tfm *tfm, const u8 *_in_key,
+ unsigned int key_len)
+{
+ struct camellia_sparc64_ctx *ctx = crypto_tfm_ctx(tfm);
+ const u32 *in_key = (const u32 *) _in_key;
+ u32 *flags = &tfm->crt_flags;
+
+ if (key_len != 16 && key_len != 24 && key_len != 32) {
+ *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+ return -EINVAL;
+ }
+
+ ctx->key_len = key_len;
+
+ camellia_sparc64_key_expand(in_key, &ctx->encrypt_key[0],
+ key_len, &ctx->decrypt_key[0]);
+ return 0;
+}
+
+extern void camellia_sparc64_crypt(const u64 *key, const u32 *input,
+ u32 *output, unsigned int key_len);
+
+static void camellia_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+ struct camellia_sparc64_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ camellia_sparc64_crypt(&ctx->encrypt_key[0],
+ (const u32 *) src,
+ (u32 *) dst, ctx->key_len);
+}
+
+static void camellia_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+ struct camellia_sparc64_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ camellia_sparc64_crypt(&ctx->decrypt_key[0],
+ (const u32 *) src,
+ (u32 *) dst, ctx->key_len);
+}
+
+extern void camellia_sparc64_load_keys(const u64 *key, unsigned int key_len);
+
+typedef void ecb_crypt_op(const u64 *input, u64 *output, unsigned int len,
+ const u64 *key);
+
+extern ecb_crypt_op camellia_sparc64_ecb_crypt_3_grand_rounds;
+extern ecb_crypt_op camellia_sparc64_ecb_crypt_4_grand_rounds;
+
+#define CAMELLIA_BLOCK_MASK (~(CAMELLIA_BLOCK_SIZE - 1))
+
+static int __ecb_crypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes, bool encrypt)
+{
+ struct camellia_sparc64_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
+ ecb_crypt_op *op;
+ const u64 *key;
+ int err;
+
+ op = camellia_sparc64_ecb_crypt_3_grand_rounds;
+ if (ctx->key_len != 16)
+ op = camellia_sparc64_ecb_crypt_4_grand_rounds;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ err = blkcipher_walk_virt(desc, &walk);
+ desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+
+ if (encrypt)
+ key = &ctx->encrypt_key[0];
+ else
+ key = &ctx->decrypt_key[0];
+ camellia_sparc64_load_keys(key, ctx->key_len);
+ while ((nbytes = walk.nbytes)) {
+ unsigned int block_len = nbytes & CAMELLIA_BLOCK_MASK;
+
+ if (likely(block_len)) {
+ const u64 *src64;
+ u64 *dst64;
+
+ src64 = (const u64 *)walk.src.virt.addr;
+ dst64 = (u64 *) walk.dst.virt.addr;
+ op(src64, dst64, block_len, key);
+ }
+ nbytes &= CAMELLIA_BLOCK_SIZE - 1;
+ err = blkcipher_walk_done(desc, &walk, nbytes);
+ }
+ fprs_write(0);
+ return err;
+}
+
+static int ecb_encrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ return __ecb_crypt(desc, dst, src, nbytes, true);
+}
+
+static int ecb_decrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ return __ecb_crypt(desc, dst, src, nbytes, false);
+}
+
+typedef void cbc_crypt_op(const u64 *input, u64 *output, unsigned int len,
+ const u64 *key, u64 *iv);
+
+extern cbc_crypt_op camellia_sparc64_cbc_encrypt_3_grand_rounds;
+extern cbc_crypt_op camellia_sparc64_cbc_encrypt_4_grand_rounds;
+extern cbc_crypt_op camellia_sparc64_cbc_decrypt_3_grand_rounds;
+extern cbc_crypt_op camellia_sparc64_cbc_decrypt_4_grand_rounds;
+
+static int cbc_encrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ struct camellia_sparc64_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
+ cbc_crypt_op *op;
+ const u64 *key;
+ int err;
+
+ op = camellia_sparc64_cbc_encrypt_3_grand_rounds;
+ if (ctx->key_len != 16)
+ op = camellia_sparc64_cbc_encrypt_4_grand_rounds;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ err = blkcipher_walk_virt(desc, &walk);
+ desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+
+ key = &ctx->encrypt_key[0];
+ camellia_sparc64_load_keys(key, ctx->key_len);
+ while ((nbytes = walk.nbytes)) {
+ unsigned int block_len = nbytes & CAMELLIA_BLOCK_MASK;
+
+ if (likely(block_len)) {
+ const u64 *src64;
+ u64 *dst64;
+
+ src64 = (const u64 *)walk.src.virt.addr;
+ dst64 = (u64 *) walk.dst.virt.addr;
+ op(src64, dst64, block_len, key,
+ (u64 *) walk.iv);
+ }
+ nbytes &= CAMELLIA_BLOCK_SIZE - 1;
+ err = blkcipher_walk_done(desc, &walk, nbytes);
+ }
+ fprs_write(0);
+ return err;
+}
+
+static int cbc_decrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ struct camellia_sparc64_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
+ cbc_crypt_op *op;
+ const u64 *key;
+ int err;
+
+ op = camellia_sparc64_cbc_decrypt_3_grand_rounds;
+ if (ctx->key_len != 16)
+ op = camellia_sparc64_cbc_decrypt_4_grand_rounds;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ err = blkcipher_walk_virt(desc, &walk);
+ desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+
+ key = &ctx->decrypt_key[0];
+ camellia_sparc64_load_keys(key, ctx->key_len);
+ while ((nbytes = walk.nbytes)) {
+ unsigned int block_len = nbytes & CAMELLIA_BLOCK_MASK;
+
+ if (likely(block_len)) {
+ const u64 *src64;
+ u64 *dst64;
+
+ src64 = (const u64 *)walk.src.virt.addr;
+ dst64 = (u64 *) walk.dst.virt.addr;
+ op(src64, dst64, block_len, key,
+ (u64 *) walk.iv);
+ }
+ nbytes &= CAMELLIA_BLOCK_SIZE - 1;
+ err = blkcipher_walk_done(desc, &walk, nbytes);
+ }
+ fprs_write(0);
+ return err;
+}
+
+static struct crypto_alg algs[] = { {
+ .cra_name = "camellia",
+ .cra_driver_name = "camellia-sparc64",
+ .cra_priority = SPARC_CR_OPCODE_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+ .cra_blocksize = CAMELLIA_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct camellia_sparc64_ctx),
+ .cra_alignmask = 3,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .cipher = {
+ .cia_min_keysize = CAMELLIA_MIN_KEY_SIZE,
+ .cia_max_keysize = CAMELLIA_MAX_KEY_SIZE,
+ .cia_setkey = camellia_set_key,
+ .cia_encrypt = camellia_encrypt,
+ .cia_decrypt = camellia_decrypt
+ }
+ }
+}, {
+ .cra_name = "ecb(camellia)",
+ .cra_driver_name = "ecb-camellia-sparc64",
+ .cra_priority = SPARC_CR_OPCODE_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_blocksize = CAMELLIA_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct camellia_sparc64_ctx),
+ .cra_alignmask = 7,
+ .cra_type = &crypto_blkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .blkcipher = {
+ .min_keysize = CAMELLIA_MIN_KEY_SIZE,
+ .max_keysize = CAMELLIA_MAX_KEY_SIZE,
+ .setkey = camellia_set_key,
+ .encrypt = ecb_encrypt,
+ .decrypt = ecb_decrypt,
+ },
+ },
+}, {
+ .cra_name = "cbc(camellia)",
+ .cra_driver_name = "cbc-camellia-sparc64",
+ .cra_priority = SPARC_CR_OPCODE_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_blocksize = CAMELLIA_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct camellia_sparc64_ctx),
+ .cra_alignmask = 7,
+ .cra_type = &crypto_blkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .blkcipher = {
+ .min_keysize = CAMELLIA_MIN_KEY_SIZE,
+ .max_keysize = CAMELLIA_MAX_KEY_SIZE,
+ .setkey = camellia_set_key,
+ .encrypt = cbc_encrypt,
+ .decrypt = cbc_decrypt,
+ },
+ },
+}
+};
+
+static bool __init sparc64_has_camellia_opcode(void)
+{
+ unsigned long cfr;
+
+ if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO))
+ return false;
+
+ __asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr));
+ if (!(cfr & CFR_CAMELLIA))
+ return false;
+
+ return true;
+}
+
+static int __init camellia_sparc64_mod_init(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(algs); i++)
+ INIT_LIST_HEAD(&algs[i].cra_list);
+
+ if (sparc64_has_camellia_opcode()) {
+ pr_info("Using sparc64 camellia opcodes optimized CAMELLIA implementation\n");
+ return crypto_register_algs(algs, ARRAY_SIZE(algs));
+ }
+ pr_info("sparc64 camellia opcodes not available.\n");
+ return -ENODEV;
+}
+
+static void __exit camellia_sparc64_mod_fini(void)
+{
+ crypto_unregister_algs(algs, ARRAY_SIZE(algs));
+}
+
+module_init(camellia_sparc64_mod_init);
+module_exit(camellia_sparc64_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Camellia Cipher Algorithm, sparc64 camellia opcode accelerated");
+
+MODULE_ALIAS("aes");
+
+#include "crop_devid.c"
diff --git a/arch/sparc/crypto/crc32c_asm.S b/arch/sparc/crypto/crc32c_asm.S
new file mode 100644
index 00000000000..2b1976e765b
--- /dev/null
+++ b/arch/sparc/crypto/crc32c_asm.S
@@ -0,0 +1,20 @@
+#include <linux/linkage.h>
+#include <asm/visasm.h>
+#include <asm/asi.h>
+
+#include "opcodes.h"
+
+ENTRY(crc32c_sparc64)
+ /* %o0=crc32p, %o1=data_ptr, %o2=len */
+ VISEntryHalf
+ lda [%o0] ASI_PL, %f1
+1: ldd [%o1], %f2
+ CRC32C(0,2,0)
+ subcc %o2, 8, %o2
+ bne,pt %icc, 1b
+ add %o1, 0x8, %o1
+ sta %f1, [%o0] ASI_PL
+ VISExitHalf
+2: retl
+ nop
+ENDPROC(crc32c_sparc64)
diff --git a/arch/sparc/crypto/crc32c_glue.c b/arch/sparc/crypto/crc32c_glue.c
new file mode 100644
index 00000000000..5162fad912c
--- /dev/null
+++ b/arch/sparc/crypto/crc32c_glue.c
@@ -0,0 +1,181 @@
+/* Glue code for CRC32C optimized for sparc64 crypto opcodes.
+ *
+ * This is based largely upon arch/x86/crypto/crc32c-intel.c
+ *
+ * Copyright (C) 2008 Intel Corporation
+ * Authors: Austin Zhang <austin_zhang@linux.intel.com>
+ * Kent Liu <kent.liu@intel.com>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/crc32.h>
+
+#include <crypto/internal/hash.h>
+
+#include <asm/pstate.h>
+#include <asm/elf.h>
+
+#include "opcodes.h"
+
+/*
+ * Setting the seed allows arbitrary accumulators and flexible XOR policy
+ * If your algorithm starts with ~0, then XOR with ~0 before you set
+ * the seed.
+ */
+static int crc32c_sparc64_setkey(struct crypto_shash *hash, const u8 *key,
+ unsigned int keylen)
+{
+ u32 *mctx = crypto_shash_ctx(hash);
+
+ if (keylen != sizeof(u32)) {
+ crypto_shash_set_flags(hash, CRYPTO_TFM_RES_BAD_KEY_LEN);
+ return -EINVAL;
+ }
+ *(__le32 *)mctx = le32_to_cpup((__le32 *)key);
+ return 0;
+}
+
+static int crc32c_sparc64_init(struct shash_desc *desc)
+{
+ u32 *mctx = crypto_shash_ctx(desc->tfm);
+ u32 *crcp = shash_desc_ctx(desc);
+
+ *crcp = *mctx;
+
+ return 0;
+}
+
+extern void crc32c_sparc64(u32 *crcp, const u64 *data, unsigned int len);
+
+static void crc32c_compute(u32 *crcp, const u64 *data, unsigned int len)
+{
+ unsigned int asm_len;
+
+ asm_len = len & ~7U;
+ if (asm_len) {
+ crc32c_sparc64(crcp, data, asm_len);
+ data += asm_len / 8;
+ len -= asm_len;
+ }
+ if (len)
+ *crcp = __crc32c_le(*crcp, (const unsigned char *) data, len);
+}
+
+static int crc32c_sparc64_update(struct shash_desc *desc, const u8 *data,
+ unsigned int len)
+{
+ u32 *crcp = shash_desc_ctx(desc);
+
+ crc32c_compute(crcp, (const u64 *) data, len);
+
+ return 0;
+}
+
+static int __crc32c_sparc64_finup(u32 *crcp, const u8 *data, unsigned int len,
+ u8 *out)
+{
+ u32 tmp = *crcp;
+
+ crc32c_compute(&tmp, (const u64 *) data, len);
+
+ *(__le32 *) out = ~cpu_to_le32(tmp);
+ return 0;
+}
+
+static int crc32c_sparc64_finup(struct shash_desc *desc, const u8 *data,
+ unsigned int len, u8 *out)
+{
+ return __crc32c_sparc64_finup(shash_desc_ctx(desc), data, len, out);
+}
+
+static int crc32c_sparc64_final(struct shash_desc *desc, u8 *out)
+{
+ u32 *crcp = shash_desc_ctx(desc);
+
+ *(__le32 *) out = ~cpu_to_le32p(crcp);
+ return 0;
+}
+
+static int crc32c_sparc64_digest(struct shash_desc *desc, const u8 *data,
+ unsigned int len, u8 *out)
+{
+ return __crc32c_sparc64_finup(crypto_shash_ctx(desc->tfm), data, len,
+ out);
+}
+
+static int crc32c_sparc64_cra_init(struct crypto_tfm *tfm)
+{
+ u32 *key = crypto_tfm_ctx(tfm);
+
+ *key = ~0;
+
+ return 0;
+}
+
+#define CHKSUM_BLOCK_SIZE 1
+#define CHKSUM_DIGEST_SIZE 4
+
+static struct shash_alg alg = {
+ .setkey = crc32c_sparc64_setkey,
+ .init = crc32c_sparc64_init,
+ .update = crc32c_sparc64_update,
+ .final = crc32c_sparc64_final,
+ .finup = crc32c_sparc64_finup,
+ .digest = crc32c_sparc64_digest,
+ .descsize = sizeof(u32),
+ .digestsize = CHKSUM_DIGEST_SIZE,
+ .base = {
+ .cra_name = "crc32c",
+ .cra_driver_name = "crc32c-sparc64",
+ .cra_priority = SPARC_CR_OPCODE_PRIORITY,
+ .cra_blocksize = CHKSUM_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(u32),
+ .cra_alignmask = 7,
+ .cra_module = THIS_MODULE,
+ .cra_init = crc32c_sparc64_cra_init,
+ }
+};
+
+static bool __init sparc64_has_crc32c_opcode(void)
+{
+ unsigned long cfr;
+
+ if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO))
+ return false;
+
+ __asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr));
+ if (!(cfr & CFR_CRC32C))
+ return false;
+
+ return true;
+}
+
+static int __init crc32c_sparc64_mod_init(void)
+{
+ if (sparc64_has_crc32c_opcode()) {
+ pr_info("Using sparc64 crc32c opcode optimized CRC32C implementation\n");
+ return crypto_register_shash(&alg);
+ }
+ pr_info("sparc64 crc32c opcode not available.\n");
+ return -ENODEV;
+}
+
+static void __exit crc32c_sparc64_mod_fini(void)
+{
+ crypto_unregister_shash(&alg);
+}
+
+module_init(crc32c_sparc64_mod_init);
+module_exit(crc32c_sparc64_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("CRC32c (Castagnoli), sparc64 crc32c opcode accelerated");
+
+MODULE_ALIAS("crc32c");
+
+#include "crop_devid.c"
diff --git a/arch/sparc/crypto/crop_devid.c b/arch/sparc/crypto/crop_devid.c
new file mode 100644
index 00000000000..5f5724a0ae2
--- /dev/null
+++ b/arch/sparc/crypto/crop_devid.c
@@ -0,0 +1,14 @@
+#include <linux/module.h>
+#include <linux/of_device.h>
+
+/* This is a dummy device table linked into all of the crypto
+ * opcode drivers. It serves to trigger the module autoloading
+ * mechanisms in userspace which scan the OF device tree and
+ * load any modules which have device table entries that
+ * match OF device nodes.
+ */
+static const struct of_device_id crypto_opcode_match[] = {
+ { .name = "cpu", .compatible = "sun4v", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, crypto_opcode_match);
diff --git a/arch/sparc/crypto/des_asm.S b/arch/sparc/crypto/des_asm.S
new file mode 100644
index 00000000000..b5c8fc269b5
--- /dev/null
+++ b/arch/sparc/crypto/des_asm.S
@@ -0,0 +1,419 @@
+#include <linux/linkage.h>
+#include <asm/visasm.h>
+
+#include "opcodes.h"
+
+ .align 32
+ENTRY(des_sparc64_key_expand)
+ /* %o0=input_key, %o1=output_key */
+ VISEntryHalf
+ ld [%o0 + 0x00], %f0
+ ld [%o0 + 0x04], %f1
+ DES_KEXPAND(0, 0, 0)
+ DES_KEXPAND(0, 1, 2)
+ DES_KEXPAND(2, 3, 6)
+ DES_KEXPAND(2, 2, 4)
+ DES_KEXPAND(6, 3, 10)
+ DES_KEXPAND(6, 2, 8)
+ DES_KEXPAND(10, 3, 14)
+ DES_KEXPAND(10, 2, 12)
+ DES_KEXPAND(14, 1, 16)
+ DES_KEXPAND(16, 3, 20)
+ DES_KEXPAND(16, 2, 18)
+ DES_KEXPAND(20, 3, 24)
+ DES_KEXPAND(20, 2, 22)
+ DES_KEXPAND(24, 3, 28)
+ DES_KEXPAND(24, 2, 26)
+ DES_KEXPAND(28, 1, 30)
+ std %f0, [%o1 + 0x00]
+ std %f2, [%o1 + 0x08]
+ std %f4, [%o1 + 0x10]
+ std %f6, [%o1 + 0x18]
+ std %f8, [%o1 + 0x20]
+ std %f10, [%o1 + 0x28]
+ std %f12, [%o1 + 0x30]
+ std %f14, [%o1 + 0x38]
+ std %f16, [%o1 + 0x40]
+ std %f18, [%o1 + 0x48]
+ std %f20, [%o1 + 0x50]
+ std %f22, [%o1 + 0x58]
+ std %f24, [%o1 + 0x60]
+ std %f26, [%o1 + 0x68]
+ std %f28, [%o1 + 0x70]
+ std %f30, [%o1 + 0x78]
+ retl
+ VISExitHalf
+ENDPROC(des_sparc64_key_expand)
+
+ .align 32
+ENTRY(des_sparc64_crypt)
+ /* %o0=key, %o1=input, %o2=output */
+ VISEntry
+ ldd [%o1 + 0x00], %f32
+ ldd [%o0 + 0x00], %f0
+ ldd [%o0 + 0x08], %f2
+ ldd [%o0 + 0x10], %f4
+ ldd [%o0 + 0x18], %f6
+ ldd [%o0 + 0x20], %f8
+ ldd [%o0 + 0x28], %f10
+ ldd [%o0 + 0x30], %f12
+ ldd [%o0 + 0x38], %f14
+ ldd [%o0 + 0x40], %f16
+ ldd [%o0 + 0x48], %f18
+ ldd [%o0 + 0x50], %f20
+ ldd [%o0 + 0x58], %f22
+ ldd [%o0 + 0x60], %f24
+ ldd [%o0 + 0x68], %f26
+ ldd [%o0 + 0x70], %f28
+ ldd [%o0 + 0x78], %f30
+ DES_IP(32, 32)
+ DES_ROUND(0, 2, 32, 32)
+ DES_ROUND(4, 6, 32, 32)
+ DES_ROUND(8, 10, 32, 32)
+ DES_ROUND(12, 14, 32, 32)
+ DES_ROUND(16, 18, 32, 32)
+ DES_ROUND(20, 22, 32, 32)
+ DES_ROUND(24, 26, 32, 32)
+ DES_ROUND(28, 30, 32, 32)
+ DES_IIP(32, 32)
+ std %f32, [%o2 + 0x00]
+ retl
+ VISExit
+ENDPROC(des_sparc64_crypt)
+
+ .align 32
+ENTRY(des_sparc64_load_keys)
+ /* %o0=key */
+ VISEntry
+ ldd [%o0 + 0x00], %f0
+ ldd [%o0 + 0x08], %f2
+ ldd [%o0 + 0x10], %f4
+ ldd [%o0 + 0x18], %f6
+ ldd [%o0 + 0x20], %f8
+ ldd [%o0 + 0x28], %f10
+ ldd [%o0 + 0x30], %f12
+ ldd [%o0 + 0x38], %f14
+ ldd [%o0 + 0x40], %f16
+ ldd [%o0 + 0x48], %f18
+ ldd [%o0 + 0x50], %f20
+ ldd [%o0 + 0x58], %f22
+ ldd [%o0 + 0x60], %f24
+ ldd [%o0 + 0x68], %f26
+ ldd [%o0 + 0x70], %f28
+ retl
+ ldd [%o0 + 0x78], %f30
+ENDPROC(des_sparc64_load_keys)
+
+ .align 32
+ENTRY(des_sparc64_ecb_crypt)
+ /* %o0=input, %o1=output, %o2=len */
+1: ldd [%o0 + 0x00], %f32
+ add %o0, 0x08, %o0
+ DES_IP(32, 32)
+ DES_ROUND(0, 2, 32, 32)
+ DES_ROUND(4, 6, 32, 32)
+ DES_ROUND(8, 10, 32, 32)
+ DES_ROUND(12, 14, 32, 32)
+ DES_ROUND(16, 18, 32, 32)
+ DES_ROUND(20, 22, 32, 32)
+ DES_ROUND(24, 26, 32, 32)
+ DES_ROUND(28, 30, 32, 32)
+ DES_IIP(32, 32)
+ std %f32, [%o1 + 0x00]
+ subcc %o2, 0x08, %o2
+ bne,pt %icc, 1b
+ add %o1, 0x08, %o1
+ retl
+ nop
+ENDPROC(des_sparc64_ecb_crypt)
+
+ .align 32
+ENTRY(des_sparc64_cbc_encrypt)
+ /* %o0=input, %o1=output, %o2=len, %o3=IV */
+ ldd [%o3 + 0x00], %f32
+1: ldd [%o0 + 0x00], %f34
+ fxor %f32, %f34, %f32
+ DES_IP(32, 32)
+ DES_ROUND(0, 2, 32, 32)
+ DES_ROUND(4, 6, 32, 32)
+ DES_ROUND(8, 10, 32, 32)
+ DES_ROUND(12, 14, 32, 32)
+ DES_ROUND(16, 18, 32, 32)
+ DES_ROUND(20, 22, 32, 32)
+ DES_ROUND(24, 26, 32, 32)
+ DES_ROUND(28, 30, 32, 32)
+ DES_IIP(32, 32)
+ std %f32, [%o1 + 0x00]
+ add %o0, 0x08, %o0
+ subcc %o2, 0x08, %o2
+ bne,pt %icc, 1b
+ add %o1, 0x08, %o1
+ retl
+ std %f32, [%o3 + 0x00]
+ENDPROC(des_sparc64_cbc_encrypt)
+
+ .align 32
+ENTRY(des_sparc64_cbc_decrypt)
+ /* %o0=input, %o1=output, %o2=len, %o3=IV */
+ ldd [%o3 + 0x00], %f34
+1: ldd [%o0 + 0x00], %f36
+ DES_IP(36, 32)
+ DES_ROUND(0, 2, 32, 32)
+ DES_ROUND(4, 6, 32, 32)
+ DES_ROUND(8, 10, 32, 32)
+ DES_ROUND(12, 14, 32, 32)
+ DES_ROUND(16, 18, 32, 32)
+ DES_ROUND(20, 22, 32, 32)
+ DES_ROUND(24, 26, 32, 32)
+ DES_ROUND(28, 30, 32, 32)
+ DES_IIP(32, 32)
+ fxor %f32, %f34, %f32
+ fsrc2 %f36, %f34
+ std %f32, [%o1 + 0x00]
+ add %o0, 0x08, %o0
+ subcc %o2, 0x08, %o2
+ bne,pt %icc, 1b
+ add %o1, 0x08, %o1
+ retl
+ std %f36, [%o3 + 0x00]
+ENDPROC(des_sparc64_cbc_decrypt)
+
+ .align 32
+ENTRY(des3_ede_sparc64_crypt)
+ /* %o0=key, %o1=input, %o2=output */
+ VISEntry
+ ldd [%o1 + 0x00], %f32
+ ldd [%o0 + 0x00], %f0
+ ldd [%o0 + 0x08], %f2
+ ldd [%o0 + 0x10], %f4
+ ldd [%o0 + 0x18], %f6
+ ldd [%o0 + 0x20], %f8
+ ldd [%o0 + 0x28], %f10
+ ldd [%o0 + 0x30], %f12
+ ldd [%o0 + 0x38], %f14
+ ldd [%o0 + 0x40], %f16
+ ldd [%o0 + 0x48], %f18
+ ldd [%o0 + 0x50], %f20
+ ldd [%o0 + 0x58], %f22
+ ldd [%o0 + 0x60], %f24
+ ldd [%o0 + 0x68], %f26
+ ldd [%o0 + 0x70], %f28
+ ldd [%o0 + 0x78], %f30
+ DES_IP(32, 32)
+ DES_ROUND(0, 2, 32, 32)
+ ldd [%o0 + 0x80], %f0
+ ldd [%o0 + 0x88], %f2
+ DES_ROUND(4, 6, 32, 32)
+ ldd [%o0 + 0x90], %f4
+ ldd [%o0 + 0x98], %f6
+ DES_ROUND(8, 10, 32, 32)
+ ldd [%o0 + 0xa0], %f8
+ ldd [%o0 + 0xa8], %f10
+ DES_ROUND(12, 14, 32, 32)
+ ldd [%o0 + 0xb0], %f12
+ ldd [%o0 + 0xb8], %f14
+ DES_ROUND(16, 18, 32, 32)
+ ldd [%o0 + 0xc0], %f16
+ ldd [%o0 + 0xc8], %f18
+ DES_ROUND(20, 22, 32, 32)
+ ldd [%o0 + 0xd0], %f20
+ ldd [%o0 + 0xd8], %f22
+ DES_ROUND(24, 26, 32, 32)
+ ldd [%o0 + 0xe0], %f24
+ ldd [%o0 + 0xe8], %f26
+ DES_ROUND(28, 30, 32, 32)
+ ldd [%o0 + 0xf0], %f28
+ ldd [%o0 + 0xf8], %f30
+ DES_IIP(32, 32)
+ DES_IP(32, 32)
+ DES_ROUND(0, 2, 32, 32)
+ ldd [%o0 + 0x100], %f0
+ ldd [%o0 + 0x108], %f2
+ DES_ROUND(4, 6, 32, 32)
+ ldd [%o0 + 0x110], %f4
+ ldd [%o0 + 0x118], %f6
+ DES_ROUND(8, 10, 32, 32)
+ ldd [%o0 + 0x120], %f8
+ ldd [%o0 + 0x128], %f10
+ DES_ROUND(12, 14, 32, 32)
+ ldd [%o0 + 0x130], %f12
+ ldd [%o0 + 0x138], %f14
+ DES_ROUND(16, 18, 32, 32)
+ ldd [%o0 + 0x140], %f16
+ ldd [%o0 + 0x148], %f18
+ DES_ROUND(20, 22, 32, 32)
+ ldd [%o0 + 0x150], %f20
+ ldd [%o0 + 0x158], %f22
+ DES_ROUND(24, 26, 32, 32)
+ ldd [%o0 + 0x160], %f24
+ ldd [%o0 + 0x168], %f26
+ DES_ROUND(28, 30, 32, 32)
+ ldd [%o0 + 0x170], %f28
+ ldd [%o0 + 0x178], %f30
+ DES_IIP(32, 32)
+ DES_IP(32, 32)
+ DES_ROUND(0, 2, 32, 32)
+ DES_ROUND(4, 6, 32, 32)
+ DES_ROUND(8, 10, 32, 32)
+ DES_ROUND(12, 14, 32, 32)
+ DES_ROUND(16, 18, 32, 32)
+ DES_ROUND(20, 22, 32, 32)
+ DES_ROUND(24, 26, 32, 32)
+ DES_ROUND(28, 30, 32, 32)
+ DES_IIP(32, 32)
+
+ std %f32, [%o2 + 0x00]
+ retl
+ VISExit
+ENDPROC(des3_ede_sparc64_crypt)
+
+ .align 32
+ENTRY(des3_ede_sparc64_load_keys)
+ /* %o0=key */
+ VISEntry
+ ldd [%o0 + 0x00], %f0
+ ldd [%o0 + 0x08], %f2
+ ldd [%o0 + 0x10], %f4
+ ldd [%o0 + 0x18], %f6
+ ldd [%o0 + 0x20], %f8
+ ldd [%o0 + 0x28], %f10
+ ldd [%o0 + 0x30], %f12
+ ldd [%o0 + 0x38], %f14
+ ldd [%o0 + 0x40], %f16
+ ldd [%o0 + 0x48], %f18
+ ldd [%o0 + 0x50], %f20
+ ldd [%o0 + 0x58], %f22
+ ldd [%o0 + 0x60], %f24
+ ldd [%o0 + 0x68], %f26
+ ldd [%o0 + 0x70], %f28
+ ldd [%o0 + 0x78], %f30
+ ldd [%o0 + 0x80], %f32
+ ldd [%o0 + 0x88], %f34
+ ldd [%o0 + 0x90], %f36
+ ldd [%o0 + 0x98], %f38
+ ldd [%o0 + 0xa0], %f40
+ ldd [%o0 + 0xa8], %f42
+ ldd [%o0 + 0xb0], %f44
+ ldd [%o0 + 0xb8], %f46
+ ldd [%o0 + 0xc0], %f48
+ ldd [%o0 + 0xc8], %f50
+ ldd [%o0 + 0xd0], %f52
+ ldd [%o0 + 0xd8], %f54
+ ldd [%o0 + 0xe0], %f56
+ retl
+ ldd [%o0 + 0xe8], %f58
+ENDPROC(des3_ede_sparc64_load_keys)
+
+#define DES3_LOOP_BODY(X) \
+ DES_IP(X, X) \
+ DES_ROUND(0, 2, X, X) \
+ DES_ROUND(4, 6, X, X) \
+ DES_ROUND(8, 10, X, X) \
+ DES_ROUND(12, 14, X, X) \
+ DES_ROUND(16, 18, X, X) \
+ ldd [%o0 + 0xf0], %f16; \
+ ldd [%o0 + 0xf8], %f18; \
+ DES_ROUND(20, 22, X, X) \
+ ldd [%o0 + 0x100], %f20; \
+ ldd [%o0 + 0x108], %f22; \
+ DES_ROUND(24, 26, X, X) \
+ ldd [%o0 + 0x110], %f24; \
+ ldd [%o0 + 0x118], %f26; \
+ DES_ROUND(28, 30, X, X) \
+ ldd [%o0 + 0x120], %f28; \
+ ldd [%o0 + 0x128], %f30; \
+ DES_IIP(X, X) \
+ DES_IP(X, X) \
+ DES_ROUND(32, 34, X, X) \
+ ldd [%o0 + 0x130], %f0; \
+ ldd [%o0 + 0x138], %f2; \
+ DES_ROUND(36, 38, X, X) \
+ ldd [%o0 + 0x140], %f4; \
+ ldd [%o0 + 0x148], %f6; \
+ DES_ROUND(40, 42, X, X) \
+ ldd [%o0 + 0x150], %f8; \
+ ldd [%o0 + 0x158], %f10; \
+ DES_ROUND(44, 46, X, X) \
+ ldd [%o0 + 0x160], %f12; \
+ ldd [%o0 + 0x168], %f14; \
+ DES_ROUND(48, 50, X, X) \
+ DES_ROUND(52, 54, X, X) \
+ DES_ROUND(56, 58, X, X) \
+ DES_ROUND(16, 18, X, X) \
+ ldd [%o0 + 0x170], %f16; \
+ ldd [%o0 + 0x178], %f18; \
+ DES_IIP(X, X) \
+ DES_IP(X, X) \
+ DES_ROUND(20, 22, X, X) \
+ ldd [%o0 + 0x50], %f20; \
+ ldd [%o0 + 0x58], %f22; \
+ DES_ROUND(24, 26, X, X) \
+ ldd [%o0 + 0x60], %f24; \
+ ldd [%o0 + 0x68], %f26; \
+ DES_ROUND(28, 30, X, X) \
+ ldd [%o0 + 0x70], %f28; \
+ ldd [%o0 + 0x78], %f30; \
+ DES_ROUND(0, 2, X, X) \
+ ldd [%o0 + 0x00], %f0; \
+ ldd [%o0 + 0x08], %f2; \
+ DES_ROUND(4, 6, X, X) \
+ ldd [%o0 + 0x10], %f4; \
+ ldd [%o0 + 0x18], %f6; \
+ DES_ROUND(8, 10, X, X) \
+ ldd [%o0 + 0x20], %f8; \
+ ldd [%o0 + 0x28], %f10; \
+ DES_ROUND(12, 14, X, X) \
+ ldd [%o0 + 0x30], %f12; \
+ ldd [%o0 + 0x38], %f14; \
+ DES_ROUND(16, 18, X, X) \
+ ldd [%o0 + 0x40], %f16; \
+ ldd [%o0 + 0x48], %f18; \
+ DES_IIP(X, X)
+
+ .align 32
+ENTRY(des3_ede_sparc64_ecb_crypt)
+ /* %o0=key, %o1=input, %o2=output, %o3=len */
+1: ldd [%o1 + 0x00], %f60
+ DES3_LOOP_BODY(60)
+ std %f60, [%o2 + 0x00]
+ add %o1, 0x08, %o1
+ subcc %o3, 0x08, %o3
+ bne,pt %icc, 1b
+ add %o2, 0x08, %o2
+ retl
+ nop
+ENDPROC(des3_ede_sparc64_ecb_crypt)
+
+ .align 32
+ENTRY(des3_ede_sparc64_cbc_encrypt)
+ /* %o0=key, %o1=input, %o2=output, %o3=len, %o4=IV */
+ ldd [%o4 + 0x00], %f60
+1: ldd [%o1 + 0x00], %f62
+ fxor %f60, %f62, %f60
+ DES3_LOOP_BODY(60)
+ std %f60, [%o2 + 0x00]
+ add %o1, 0x08, %o1
+ subcc %o3, 0x08, %o3
+ bne,pt %icc, 1b
+ add %o2, 0x08, %o2
+ retl
+ std %f60, [%o4 + 0x00]
+ENDPROC(des3_ede_sparc64_cbc_encrypt)
+
+ .align 32
+ENTRY(des3_ede_sparc64_cbc_decrypt)
+ /* %o0=key, %o1=input, %o2=output, %o3=len, %o4=IV */
+ ldd [%o4 + 0x00], %f62
+1: ldx [%o1 + 0x00], %g1
+ MOVXTOD_G1_F60
+ DES3_LOOP_BODY(60)
+ fxor %f62, %f60, %f60
+ MOVXTOD_G1_F62
+ std %f60, [%o2 + 0x00]
+ add %o1, 0x08, %o1
+ subcc %o3, 0x08, %o3
+ bne,pt %icc, 1b
+ add %o2, 0x08, %o2
+ retl
+ stx %g1, [%o4 + 0x00]
+ENDPROC(des3_ede_sparc64_cbc_decrypt)
diff --git a/arch/sparc/crypto/des_glue.c b/arch/sparc/crypto/des_glue.c
new file mode 100644
index 00000000000..3065bc61f9d
--- /dev/null
+++ b/arch/sparc/crypto/des_glue.c
@@ -0,0 +1,537 @@
+/* Glue code for DES encryption optimized for sparc64 crypto opcodes.
+ *
+ * Copyright (C) 2012 David S. Miller <davem@davemloft.net>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/crypto.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/types.h>
+#include <crypto/algapi.h>
+#include <crypto/des.h>
+
+#include <asm/fpumacro.h>
+#include <asm/pstate.h>
+#include <asm/elf.h>
+
+#include "opcodes.h"
+
+struct des_sparc64_ctx {
+ u64 encrypt_expkey[DES_EXPKEY_WORDS / 2];
+ u64 decrypt_expkey[DES_EXPKEY_WORDS / 2];
+};
+
+struct des3_ede_sparc64_ctx {
+ u64 encrypt_expkey[DES3_EDE_EXPKEY_WORDS / 2];
+ u64 decrypt_expkey[DES3_EDE_EXPKEY_WORDS / 2];
+};
+
+static void encrypt_to_decrypt(u64 *d, const u64 *e)
+{
+ const u64 *s = e + (DES_EXPKEY_WORDS / 2) - 1;
+ int i;
+
+ for (i = 0; i < DES_EXPKEY_WORDS / 2; i++)
+ *d++ = *s--;
+}
+
+extern void des_sparc64_key_expand(const u32 *input_key, u64 *key);
+
+static int des_set_key(struct crypto_tfm *tfm, const u8 *key,
+ unsigned int keylen)
+{
+ struct des_sparc64_ctx *dctx = crypto_tfm_ctx(tfm);
+ u32 *flags = &tfm->crt_flags;
+ u32 tmp[DES_EXPKEY_WORDS];
+ int ret;
+
+ /* Even though we have special instructions for key expansion,
+ * we call des_ekey() so that we don't have to write our own
+ * weak key detection code.
+ */
+ ret = des_ekey(tmp, key);
+ if (unlikely(ret == 0) && (*flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
+ *flags |= CRYPTO_TFM_RES_WEAK_KEY;
+ return -EINVAL;
+ }
+
+ des_sparc64_key_expand((const u32 *) key, &dctx->encrypt_expkey[0]);
+ encrypt_to_decrypt(&dctx->decrypt_expkey[0], &dctx->encrypt_expkey[0]);
+
+ return 0;
+}
+
+extern void des_sparc64_crypt(const u64 *key, const u64 *input,
+ u64 *output);
+
+static void des_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+ struct des_sparc64_ctx *ctx = crypto_tfm_ctx(tfm);
+ const u64 *K = ctx->encrypt_expkey;
+
+ des_sparc64_crypt(K, (const u64 *) src, (u64 *) dst);
+}
+
+static void des_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+ struct des_sparc64_ctx *ctx = crypto_tfm_ctx(tfm);
+ const u64 *K = ctx->decrypt_expkey;
+
+ des_sparc64_crypt(K, (const u64 *) src, (u64 *) dst);
+}
+
+extern void des_sparc64_load_keys(const u64 *key);
+
+extern void des_sparc64_ecb_crypt(const u64 *input, u64 *output,
+ unsigned int len);
+
+#define DES_BLOCK_MASK (~(DES_BLOCK_SIZE - 1))
+
+static int __ecb_crypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes, bool encrypt)
+{
+ struct des_sparc64_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
+ int err;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ err = blkcipher_walk_virt(desc, &walk);
+ desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+
+ if (encrypt)
+ des_sparc64_load_keys(&ctx->encrypt_expkey[0]);
+ else
+ des_sparc64_load_keys(&ctx->decrypt_expkey[0]);
+ while ((nbytes = walk.nbytes)) {
+ unsigned int block_len = nbytes & DES_BLOCK_MASK;
+
+ if (likely(block_len)) {
+ des_sparc64_ecb_crypt((const u64 *)walk.src.virt.addr,
+ (u64 *) walk.dst.virt.addr,
+ block_len);
+ }
+ nbytes &= DES_BLOCK_SIZE - 1;
+ err = blkcipher_walk_done(desc, &walk, nbytes);
+ }
+ fprs_write(0);
+ return err;
+}
+
+static int ecb_encrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ return __ecb_crypt(desc, dst, src, nbytes, true);
+}
+
+static int ecb_decrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ return __ecb_crypt(desc, dst, src, nbytes, false);
+}
+
+extern void des_sparc64_cbc_encrypt(const u64 *input, u64 *output,
+ unsigned int len, u64 *iv);
+
+static int cbc_encrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ struct des_sparc64_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
+ int err;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ err = blkcipher_walk_virt(desc, &walk);
+ desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+
+ des_sparc64_load_keys(&ctx->encrypt_expkey[0]);
+ while ((nbytes = walk.nbytes)) {
+ unsigned int block_len = nbytes & DES_BLOCK_MASK;
+
+ if (likely(block_len)) {
+ des_sparc64_cbc_encrypt((const u64 *)walk.src.virt.addr,
+ (u64 *) walk.dst.virt.addr,
+ block_len, (u64 *) walk.iv);
+ }
+ nbytes &= DES_BLOCK_SIZE - 1;
+ err = blkcipher_walk_done(desc, &walk, nbytes);
+ }
+ fprs_write(0);
+ return err;
+}
+
+extern void des_sparc64_cbc_decrypt(const u64 *input, u64 *output,
+ unsigned int len, u64 *iv);
+
+static int cbc_decrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ struct des_sparc64_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
+ int err;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ err = blkcipher_walk_virt(desc, &walk);
+ desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+
+ des_sparc64_load_keys(&ctx->decrypt_expkey[0]);
+ while ((nbytes = walk.nbytes)) {
+ unsigned int block_len = nbytes & DES_BLOCK_MASK;
+
+ if (likely(block_len)) {
+ des_sparc64_cbc_decrypt((const u64 *)walk.src.virt.addr,
+ (u64 *) walk.dst.virt.addr,
+ block_len, (u64 *) walk.iv);
+ }
+ nbytes &= DES_BLOCK_SIZE - 1;
+ err = blkcipher_walk_done(desc, &walk, nbytes);
+ }
+ fprs_write(0);
+ return err;
+}
+
+static int des3_ede_set_key(struct crypto_tfm *tfm, const u8 *key,
+ unsigned int keylen)
+{
+ struct des3_ede_sparc64_ctx *dctx = crypto_tfm_ctx(tfm);
+ const u32 *K = (const u32 *)key;
+ u32 *flags = &tfm->crt_flags;
+ u64 k1[DES_EXPKEY_WORDS / 2];
+ u64 k2[DES_EXPKEY_WORDS / 2];
+ u64 k3[DES_EXPKEY_WORDS / 2];
+
+ if (unlikely(!((K[0] ^ K[2]) | (K[1] ^ K[3])) ||
+ !((K[2] ^ K[4]) | (K[3] ^ K[5]))) &&
+ (*flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
+ *flags |= CRYPTO_TFM_RES_WEAK_KEY;
+ return -EINVAL;
+ }
+
+ des_sparc64_key_expand((const u32 *)key, k1);
+ key += DES_KEY_SIZE;
+ des_sparc64_key_expand((const u32 *)key, k2);
+ key += DES_KEY_SIZE;
+ des_sparc64_key_expand((const u32 *)key, k3);
+
+ memcpy(&dctx->encrypt_expkey[0], &k1[0], sizeof(k1));
+ encrypt_to_decrypt(&dctx->encrypt_expkey[DES_EXPKEY_WORDS / 2], &k2[0]);
+ memcpy(&dctx->encrypt_expkey[(DES_EXPKEY_WORDS / 2) * 2],
+ &k3[0], sizeof(k3));
+
+ encrypt_to_decrypt(&dctx->decrypt_expkey[0], &k3[0]);
+ memcpy(&dctx->decrypt_expkey[DES_EXPKEY_WORDS / 2],
+ &k2[0], sizeof(k2));
+ encrypt_to_decrypt(&dctx->decrypt_expkey[(DES_EXPKEY_WORDS / 2) * 2],
+ &k1[0]);
+
+ return 0;
+}
+
+extern void des3_ede_sparc64_crypt(const u64 *key, const u64 *input,
+ u64 *output);
+
+static void des3_ede_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+ struct des3_ede_sparc64_ctx *ctx = crypto_tfm_ctx(tfm);
+ const u64 *K = ctx->encrypt_expkey;
+
+ des3_ede_sparc64_crypt(K, (const u64 *) src, (u64 *) dst);
+}
+
+static void des3_ede_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+ struct des3_ede_sparc64_ctx *ctx = crypto_tfm_ctx(tfm);
+ const u64 *K = ctx->decrypt_expkey;
+
+ des3_ede_sparc64_crypt(K, (const u64 *) src, (u64 *) dst);
+}
+
+extern void des3_ede_sparc64_load_keys(const u64 *key);
+
+extern void des3_ede_sparc64_ecb_crypt(const u64 *expkey, const u64 *input,
+ u64 *output, unsigned int len);
+
+static int __ecb3_crypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes, bool encrypt)
+{
+ struct des3_ede_sparc64_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
+ const u64 *K;
+ int err;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ err = blkcipher_walk_virt(desc, &walk);
+ desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+
+ if (encrypt)
+ K = &ctx->encrypt_expkey[0];
+ else
+ K = &ctx->decrypt_expkey[0];
+ des3_ede_sparc64_load_keys(K);
+ while ((nbytes = walk.nbytes)) {
+ unsigned int block_len = nbytes & DES_BLOCK_MASK;
+
+ if (likely(block_len)) {
+ const u64 *src64 = (const u64 *)walk.src.virt.addr;
+ des3_ede_sparc64_ecb_crypt(K, src64,
+ (u64 *) walk.dst.virt.addr,
+ block_len);
+ }
+ nbytes &= DES_BLOCK_SIZE - 1;
+ err = blkcipher_walk_done(desc, &walk, nbytes);
+ }
+ fprs_write(0);
+ return err;
+}
+
+static int ecb3_encrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ return __ecb3_crypt(desc, dst, src, nbytes, true);
+}
+
+static int ecb3_decrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ return __ecb3_crypt(desc, dst, src, nbytes, false);
+}
+
+extern void des3_ede_sparc64_cbc_encrypt(const u64 *expkey, const u64 *input,
+ u64 *output, unsigned int len,
+ u64 *iv);
+
+static int cbc3_encrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ struct des3_ede_sparc64_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
+ const u64 *K;
+ int err;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ err = blkcipher_walk_virt(desc, &walk);
+ desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+
+ K = &ctx->encrypt_expkey[0];
+ des3_ede_sparc64_load_keys(K);
+ while ((nbytes = walk.nbytes)) {
+ unsigned int block_len = nbytes & DES_BLOCK_MASK;
+
+ if (likely(block_len)) {
+ const u64 *src64 = (const u64 *)walk.src.virt.addr;
+ des3_ede_sparc64_cbc_encrypt(K, src64,
+ (u64 *) walk.dst.virt.addr,
+ block_len,
+ (u64 *) walk.iv);
+ }
+ nbytes &= DES_BLOCK_SIZE - 1;
+ err = blkcipher_walk_done(desc, &walk, nbytes);
+ }
+ fprs_write(0);
+ return err;
+}
+
+extern void des3_ede_sparc64_cbc_decrypt(const u64 *expkey, const u64 *input,
+ u64 *output, unsigned int len,
+ u64 *iv);
+
+static int cbc3_decrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ struct des3_ede_sparc64_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
+ const u64 *K;
+ int err;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ err = blkcipher_walk_virt(desc, &walk);
+ desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+
+ K = &ctx->decrypt_expkey[0];
+ des3_ede_sparc64_load_keys(K);
+ while ((nbytes = walk.nbytes)) {
+ unsigned int block_len = nbytes & DES_BLOCK_MASK;
+
+ if (likely(block_len)) {
+ const u64 *src64 = (const u64 *)walk.src.virt.addr;
+ des3_ede_sparc64_cbc_decrypt(K, src64,
+ (u64 *) walk.dst.virt.addr,
+ block_len,
+ (u64 *) walk.iv);
+ }
+ nbytes &= DES_BLOCK_SIZE - 1;
+ err = blkcipher_walk_done(desc, &walk, nbytes);
+ }
+ fprs_write(0);
+ return err;
+}
+
+static struct crypto_alg algs[] = { {
+ .cra_name = "des",
+ .cra_driver_name = "des-sparc64",
+ .cra_priority = SPARC_CR_OPCODE_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+ .cra_blocksize = DES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct des_sparc64_ctx),
+ .cra_alignmask = 7,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .cipher = {
+ .cia_min_keysize = DES_KEY_SIZE,
+ .cia_max_keysize = DES_KEY_SIZE,
+ .cia_setkey = des_set_key,
+ .cia_encrypt = des_encrypt,
+ .cia_decrypt = des_decrypt
+ }
+ }
+}, {
+ .cra_name = "ecb(des)",
+ .cra_driver_name = "ecb-des-sparc64",
+ .cra_priority = SPARC_CR_OPCODE_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_blocksize = DES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct des_sparc64_ctx),
+ .cra_alignmask = 7,
+ .cra_type = &crypto_blkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .blkcipher = {
+ .min_keysize = DES_KEY_SIZE,
+ .max_keysize = DES_KEY_SIZE,
+ .setkey = des_set_key,
+ .encrypt = ecb_encrypt,
+ .decrypt = ecb_decrypt,
+ },
+ },
+}, {
+ .cra_name = "cbc(des)",
+ .cra_driver_name = "cbc-des-sparc64",
+ .cra_priority = SPARC_CR_OPCODE_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_blocksize = DES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct des_sparc64_ctx),
+ .cra_alignmask = 7,
+ .cra_type = &crypto_blkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .blkcipher = {
+ .min_keysize = DES_KEY_SIZE,
+ .max_keysize = DES_KEY_SIZE,
+ .setkey = des_set_key,
+ .encrypt = cbc_encrypt,
+ .decrypt = cbc_decrypt,
+ },
+ },
+}, {
+ .cra_name = "des3_ede",
+ .cra_driver_name = "des3_ede-sparc64",
+ .cra_priority = SPARC_CR_OPCODE_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+ .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct des3_ede_sparc64_ctx),
+ .cra_alignmask = 7,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .cipher = {
+ .cia_min_keysize = DES3_EDE_KEY_SIZE,
+ .cia_max_keysize = DES3_EDE_KEY_SIZE,
+ .cia_setkey = des3_ede_set_key,
+ .cia_encrypt = des3_ede_encrypt,
+ .cia_decrypt = des3_ede_decrypt
+ }
+ }
+}, {
+ .cra_name = "ecb(des3_ede)",
+ .cra_driver_name = "ecb-des3_ede-sparc64",
+ .cra_priority = SPARC_CR_OPCODE_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct des3_ede_sparc64_ctx),
+ .cra_alignmask = 7,
+ .cra_type = &crypto_blkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .blkcipher = {
+ .min_keysize = DES3_EDE_KEY_SIZE,
+ .max_keysize = DES3_EDE_KEY_SIZE,
+ .setkey = des3_ede_set_key,
+ .encrypt = ecb3_encrypt,
+ .decrypt = ecb3_decrypt,
+ },
+ },
+}, {
+ .cra_name = "cbc(des3_ede)",
+ .cra_driver_name = "cbc-des3_ede-sparc64",
+ .cra_priority = SPARC_CR_OPCODE_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct des3_ede_sparc64_ctx),
+ .cra_alignmask = 7,
+ .cra_type = &crypto_blkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .blkcipher = {
+ .min_keysize = DES3_EDE_KEY_SIZE,
+ .max_keysize = DES3_EDE_KEY_SIZE,
+ .setkey = des3_ede_set_key,
+ .encrypt = cbc3_encrypt,
+ .decrypt = cbc3_decrypt,
+ },
+ },
+} };
+
+static bool __init sparc64_has_des_opcode(void)
+{
+ unsigned long cfr;
+
+ if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO))
+ return false;
+
+ __asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr));
+ if (!(cfr & CFR_DES))
+ return false;
+
+ return true;
+}
+
+static int __init des_sparc64_mod_init(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(algs); i++)
+ INIT_LIST_HEAD(&algs[i].cra_list);
+
+ if (sparc64_has_des_opcode()) {
+ pr_info("Using sparc64 des opcodes optimized DES implementation\n");
+ return crypto_register_algs(algs, ARRAY_SIZE(algs));
+ }
+ pr_info("sparc64 des opcodes not available.\n");
+ return -ENODEV;
+}
+
+static void __exit des_sparc64_mod_fini(void)
+{
+ crypto_unregister_algs(algs, ARRAY_SIZE(algs));
+}
+
+module_init(des_sparc64_mod_init);
+module_exit(des_sparc64_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms, sparc64 des opcode accelerated");
+
+MODULE_ALIAS("des");
+
+#include "crop_devid.c"
diff --git a/arch/sparc/crypto/md5_asm.S b/arch/sparc/crypto/md5_asm.S
new file mode 100644
index 00000000000..3150404e602
--- /dev/null
+++ b/arch/sparc/crypto/md5_asm.S
@@ -0,0 +1,70 @@
+#include <linux/linkage.h>
+#include <asm/visasm.h>
+
+#include "opcodes.h"
+
+ENTRY(md5_sparc64_transform)
+ /* %o0 = digest, %o1 = data, %o2 = rounds */
+ VISEntryHalf
+ ld [%o0 + 0x00], %f0
+ ld [%o0 + 0x04], %f1
+ andcc %o1, 0x7, %g0
+ ld [%o0 + 0x08], %f2
+ bne,pn %xcc, 10f
+ ld [%o0 + 0x0c], %f3
+
+1:
+ ldd [%o1 + 0x00], %f8
+ ldd [%o1 + 0x08], %f10
+ ldd [%o1 + 0x10], %f12
+ ldd [%o1 + 0x18], %f14
+ ldd [%o1 + 0x20], %f16
+ ldd [%o1 + 0x28], %f18
+ ldd [%o1 + 0x30], %f20
+ ldd [%o1 + 0x38], %f22
+
+ MD5
+
+ subcc %o2, 1, %o2
+ bne,pt %xcc, 1b
+ add %o1, 0x40, %o1
+
+5:
+ st %f0, [%o0 + 0x00]
+ st %f1, [%o0 + 0x04]
+ st %f2, [%o0 + 0x08]
+ st %f3, [%o0 + 0x0c]
+ retl
+ VISExitHalf
+10:
+ alignaddr %o1, %g0, %o1
+
+ ldd [%o1 + 0x00], %f10
+1:
+ ldd [%o1 + 0x08], %f12
+ ldd [%o1 + 0x10], %f14
+ ldd [%o1 + 0x18], %f16
+ ldd [%o1 + 0x20], %f18
+ ldd [%o1 + 0x28], %f20
+ ldd [%o1 + 0x30], %f22
+ ldd [%o1 + 0x38], %f24
+ ldd [%o1 + 0x40], %f26
+
+ faligndata %f10, %f12, %f8
+ faligndata %f12, %f14, %f10
+ faligndata %f14, %f16, %f12
+ faligndata %f16, %f18, %f14
+ faligndata %f18, %f20, %f16
+ faligndata %f20, %f22, %f18
+ faligndata %f22, %f24, %f20
+ faligndata %f24, %f26, %f22
+
+ MD5
+
+ subcc %o2, 1, %o2
+ fsrc2 %f26, %f10
+ bne,pt %xcc, 1b
+ add %o1, 0x40, %o1
+
+ ba,a,pt %xcc, 5b
+ENDPROC(md5_sparc64_transform)
diff --git a/arch/sparc/crypto/md5_glue.c b/arch/sparc/crypto/md5_glue.c
new file mode 100644
index 00000000000..09a9ea1dfb6
--- /dev/null
+++ b/arch/sparc/crypto/md5_glue.c
@@ -0,0 +1,190 @@
+/* Glue code for MD5 hashing optimized for sparc64 crypto opcodes.
+ *
+ * This is based largely upon arch/x86/crypto/sha1_ssse3_glue.c
+ * and crypto/md5.c which are:
+ *
+ * Copyright (c) Alan Smithee.
+ * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
+ * Copyright (c) Jean-Francois Dive <jef@linuxbe.org>
+ * Copyright (c) Mathias Krause <minipli@googlemail.com>
+ * Copyright (c) Cryptoapi developers.
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <crypto/internal/hash.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/cryptohash.h>
+#include <linux/types.h>
+#include <crypto/md5.h>
+
+#include <asm/pstate.h>
+#include <asm/elf.h>
+
+#include "opcodes.h"
+
+asmlinkage void md5_sparc64_transform(u32 *digest, const char *data,
+ unsigned int rounds);
+
+static int md5_sparc64_init(struct shash_desc *desc)
+{
+ struct md5_state *mctx = shash_desc_ctx(desc);
+
+ mctx->hash[0] = cpu_to_le32(0x67452301);
+ mctx->hash[1] = cpu_to_le32(0xefcdab89);
+ mctx->hash[2] = cpu_to_le32(0x98badcfe);
+ mctx->hash[3] = cpu_to_le32(0x10325476);
+ mctx->byte_count = 0;
+
+ return 0;
+}
+
+static void __md5_sparc64_update(struct md5_state *sctx, const u8 *data,
+ unsigned int len, unsigned int partial)
+{
+ unsigned int done = 0;
+
+ sctx->byte_count += len;
+ if (partial) {
+ done = MD5_HMAC_BLOCK_SIZE - partial;
+ memcpy((u8 *)sctx->block + partial, data, done);
+ md5_sparc64_transform(sctx->hash, (u8 *)sctx->block, 1);
+ }
+ if (len - done >= MD5_HMAC_BLOCK_SIZE) {
+ const unsigned int rounds = (len - done) / MD5_HMAC_BLOCK_SIZE;
+
+ md5_sparc64_transform(sctx->hash, data + done, rounds);
+ done += rounds * MD5_HMAC_BLOCK_SIZE;
+ }
+
+ memcpy(sctx->block, data + done, len - done);
+}
+
+static int md5_sparc64_update(struct shash_desc *desc, const u8 *data,
+ unsigned int len)
+{
+ struct md5_state *sctx = shash_desc_ctx(desc);
+ unsigned int partial = sctx->byte_count % MD5_HMAC_BLOCK_SIZE;
+
+ /* Handle the fast case right here */
+ if (partial + len < MD5_HMAC_BLOCK_SIZE) {
+ sctx->byte_count += len;
+ memcpy((u8 *)sctx->block + partial, data, len);
+ } else
+ __md5_sparc64_update(sctx, data, len, partial);
+
+ return 0;
+}
+
+/* Add padding and return the message digest. */
+static int md5_sparc64_final(struct shash_desc *desc, u8 *out)
+{
+ struct md5_state *sctx = shash_desc_ctx(desc);
+ unsigned int i, index, padlen;
+ u32 *dst = (u32 *)out;
+ __le64 bits;
+ static const u8 padding[MD5_HMAC_BLOCK_SIZE] = { 0x80, };
+
+ bits = cpu_to_le64(sctx->byte_count << 3);
+
+ /* Pad out to 56 mod 64 and append length */
+ index = sctx->byte_count % MD5_HMAC_BLOCK_SIZE;
+ padlen = (index < 56) ? (56 - index) : ((MD5_HMAC_BLOCK_SIZE+56) - index);
+
+ /* We need to fill a whole block for __md5_sparc64_update() */
+ if (padlen <= 56) {
+ sctx->byte_count += padlen;
+ memcpy((u8 *)sctx->block + index, padding, padlen);
+ } else {
+ __md5_sparc64_update(sctx, padding, padlen, index);
+ }
+ __md5_sparc64_update(sctx, (const u8 *)&bits, sizeof(bits), 56);
+
+ /* Store state in digest */
+ for (i = 0; i < MD5_HASH_WORDS; i++)
+ dst[i] = sctx->hash[i];
+
+ /* Wipe context */
+ memset(sctx, 0, sizeof(*sctx));
+
+ return 0;
+}
+
+static int md5_sparc64_export(struct shash_desc *desc, void *out)
+{
+ struct md5_state *sctx = shash_desc_ctx(desc);
+
+ memcpy(out, sctx, sizeof(*sctx));
+
+ return 0;
+}
+
+static int md5_sparc64_import(struct shash_desc *desc, const void *in)
+{
+ struct md5_state *sctx = shash_desc_ctx(desc);
+
+ memcpy(sctx, in, sizeof(*sctx));
+
+ return 0;
+}
+
+static struct shash_alg alg = {
+ .digestsize = MD5_DIGEST_SIZE,
+ .init = md5_sparc64_init,
+ .update = md5_sparc64_update,
+ .final = md5_sparc64_final,
+ .export = md5_sparc64_export,
+ .import = md5_sparc64_import,
+ .descsize = sizeof(struct md5_state),
+ .statesize = sizeof(struct md5_state),
+ .base = {
+ .cra_name = "md5",
+ .cra_driver_name= "md5-sparc64",
+ .cra_priority = SPARC_CR_OPCODE_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_SHASH,
+ .cra_blocksize = MD5_HMAC_BLOCK_SIZE,
+ .cra_module = THIS_MODULE,
+ }
+};
+
+static bool __init sparc64_has_md5_opcode(void)
+{
+ unsigned long cfr;
+
+ if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO))
+ return false;
+
+ __asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr));
+ if (!(cfr & CFR_MD5))
+ return false;
+
+ return true;
+}
+
+static int __init md5_sparc64_mod_init(void)
+{
+ if (sparc64_has_md5_opcode()) {
+ pr_info("Using sparc64 md5 opcode optimized MD5 implementation\n");
+ return crypto_register_shash(&alg);
+ }
+ pr_info("sparc64 md5 opcode not available.\n");
+ return -ENODEV;
+}
+
+static void __exit md5_sparc64_mod_fini(void)
+{
+ crypto_unregister_shash(&alg);
+}
+
+module_init(md5_sparc64_mod_init);
+module_exit(md5_sparc64_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("MD5 Secure Hash Algorithm, sparc64 md5 opcode accelerated");
+
+MODULE_ALIAS("md5");
+
+#include "crop_devid.c"
diff --git a/arch/sparc/crypto/opcodes.h b/arch/sparc/crypto/opcodes.h
new file mode 100644
index 00000000000..19cbaea6976
--- /dev/null
+++ b/arch/sparc/crypto/opcodes.h
@@ -0,0 +1,99 @@
+#ifndef _OPCODES_H
+#define _OPCODES_H
+
+#define SPARC_CR_OPCODE_PRIORITY 300
+
+#define F3F(x,y,z) (((x)<<30)|((y)<<19)|((z)<<5))
+
+#define FPD_ENCODE(x) (((x) >> 5) | ((x) & ~(0x20)))
+
+#define RS1(x) (FPD_ENCODE(x) << 14)
+#define RS2(x) (FPD_ENCODE(x) << 0)
+#define RS3(x) (FPD_ENCODE(x) << 9)
+#define RD(x) (FPD_ENCODE(x) << 25)
+#define IMM5_0(x) ((x) << 0)
+#define IMM5_9(x) ((x) << 9)
+
+#define CRC32C(a,b,c) \
+ .word (F3F(2,0x36,0x147)|RS1(a)|RS2(b)|RD(c));
+
+#define MD5 \
+ .word 0x81b02800;
+#define SHA1 \
+ .word 0x81b02820;
+#define SHA256 \
+ .word 0x81b02840;
+#define SHA512 \
+ .word 0x81b02860;
+
+#define AES_EROUND01(a,b,c,d) \
+ .word (F3F(2, 0x19, 0)|RS1(a)|RS2(b)|RS3(c)|RD(d));
+#define AES_EROUND23(a,b,c,d) \
+ .word (F3F(2, 0x19, 1)|RS1(a)|RS2(b)|RS3(c)|RD(d));
+#define AES_DROUND01(a,b,c,d) \
+ .word (F3F(2, 0x19, 2)|RS1(a)|RS2(b)|RS3(c)|RD(d));
+#define AES_DROUND23(a,b,c,d) \
+ .word (F3F(2, 0x19, 3)|RS1(a)|RS2(b)|RS3(c)|RD(d));
+#define AES_EROUND01_L(a,b,c,d) \
+ .word (F3F(2, 0x19, 4)|RS1(a)|RS2(b)|RS3(c)|RD(d));
+#define AES_EROUND23_L(a,b,c,d) \
+ .word (F3F(2, 0x19, 5)|RS1(a)|RS2(b)|RS3(c)|RD(d));
+#define AES_DROUND01_L(a,b,c,d) \
+ .word (F3F(2, 0x19, 6)|RS1(a)|RS2(b)|RS3(c)|RD(d));
+#define AES_DROUND23_L(a,b,c,d) \
+ .word (F3F(2, 0x19, 7)|RS1(a)|RS2(b)|RS3(c)|RD(d));
+#define AES_KEXPAND1(a,b,c,d) \
+ .word (F3F(2, 0x19, 8)|RS1(a)|RS2(b)|IMM5_9(c)|RD(d));
+#define AES_KEXPAND0(a,b,c) \
+ .word (F3F(2, 0x36, 0x130)|RS1(a)|RS2(b)|RD(c));
+#define AES_KEXPAND2(a,b,c) \
+ .word (F3F(2, 0x36, 0x131)|RS1(a)|RS2(b)|RD(c));
+
+#define DES_IP(a,b) \
+ .word (F3F(2, 0x36, 0x134)|RS1(a)|RD(b));
+#define DES_IIP(a,b) \
+ .word (F3F(2, 0x36, 0x135)|RS1(a)|RD(b));
+#define DES_KEXPAND(a,b,c) \
+ .word (F3F(2, 0x36, 0x136)|RS1(a)|IMM5_0(b)|RD(c));
+#define DES_ROUND(a,b,c,d) \
+ .word (F3F(2, 0x19, 0x009)|RS1(a)|RS2(b)|RS3(c)|RD(d));
+
+#define CAMELLIA_F(a,b,c,d) \
+ .word (F3F(2, 0x19, 0x00c)|RS1(a)|RS2(b)|RS3(c)|RD(d));
+#define CAMELLIA_FL(a,b,c) \
+ .word (F3F(2, 0x36, 0x13c)|RS1(a)|RS2(b)|RD(c));
+#define CAMELLIA_FLI(a,b,c) \
+ .word (F3F(2, 0x36, 0x13d)|RS1(a)|RS2(b)|RD(c));
+
+#define MOVDTOX_F0_O4 \
+ .word 0x99b02200
+#define MOVDTOX_F2_O5 \
+ .word 0x9bb02202
+#define MOVXTOD_G1_F60 \
+ .word 0xbbb02301
+#define MOVXTOD_G1_F62 \
+ .word 0xbfb02301
+#define MOVXTOD_G3_F4 \
+ .word 0x89b02303;
+#define MOVXTOD_G7_F6 \
+ .word 0x8db02307;
+#define MOVXTOD_G3_F0 \
+ .word 0x81b02303;
+#define MOVXTOD_G7_F2 \
+ .word 0x85b02307;
+#define MOVXTOD_O0_F0 \
+ .word 0x81b02308;
+#define MOVXTOD_O5_F0 \
+ .word 0x81b0230d;
+#define MOVXTOD_O5_F2 \
+ .word 0x85b0230d;
+#define MOVXTOD_O5_F4 \
+ .word 0x89b0230d;
+#define MOVXTOD_O5_F6 \
+ .word 0x8db0230d;
+#define MOVXTOD_G3_F60 \
+ .word 0xbbb02303;
+#define MOVXTOD_G7_F62 \
+ .word 0xbfb02307;
+
+#endif /* _OPCODES_H */
diff --git a/arch/sparc/crypto/sha1_asm.S b/arch/sparc/crypto/sha1_asm.S
new file mode 100644
index 00000000000..219d10c5ae0
--- /dev/null
+++ b/arch/sparc/crypto/sha1_asm.S
@@ -0,0 +1,72 @@
+#include <linux/linkage.h>
+#include <asm/visasm.h>
+
+#include "opcodes.h"
+
+ENTRY(sha1_sparc64_transform)
+ /* %o0 = digest, %o1 = data, %o2 = rounds */
+ VISEntryHalf
+ ld [%o0 + 0x00], %f0
+ ld [%o0 + 0x04], %f1
+ ld [%o0 + 0x08], %f2
+ andcc %o1, 0x7, %g0
+ ld [%o0 + 0x0c], %f3
+ bne,pn %xcc, 10f
+ ld [%o0 + 0x10], %f4
+
+1:
+ ldd [%o1 + 0x00], %f8
+ ldd [%o1 + 0x08], %f10
+ ldd [%o1 + 0x10], %f12
+ ldd [%o1 + 0x18], %f14
+ ldd [%o1 + 0x20], %f16
+ ldd [%o1 + 0x28], %f18
+ ldd [%o1 + 0x30], %f20
+ ldd [%o1 + 0x38], %f22
+
+ SHA1
+
+ subcc %o2, 1, %o2
+ bne,pt %xcc, 1b
+ add %o1, 0x40, %o1
+
+5:
+ st %f0, [%o0 + 0x00]
+ st %f1, [%o0 + 0x04]
+ st %f2, [%o0 + 0x08]
+ st %f3, [%o0 + 0x0c]
+ st %f4, [%o0 + 0x10]
+ retl
+ VISExitHalf
+10:
+ alignaddr %o1, %g0, %o1
+
+ ldd [%o1 + 0x00], %f10
+1:
+ ldd [%o1 + 0x08], %f12
+ ldd [%o1 + 0x10], %f14
+ ldd [%o1 + 0x18], %f16
+ ldd [%o1 + 0x20], %f18
+ ldd [%o1 + 0x28], %f20
+ ldd [%o1 + 0x30], %f22
+ ldd [%o1 + 0x38], %f24
+ ldd [%o1 + 0x40], %f26
+
+ faligndata %f10, %f12, %f8
+ faligndata %f12, %f14, %f10
+ faligndata %f14, %f16, %f12
+ faligndata %f16, %f18, %f14
+ faligndata %f18, %f20, %f16
+ faligndata %f20, %f22, %f18
+ faligndata %f22, %f24, %f20
+ faligndata %f24, %f26, %f22
+
+ SHA1
+
+ subcc %o2, 1, %o2
+ fsrc2 %f26, %f10
+ bne,pt %xcc, 1b
+ add %o1, 0x40, %o1
+
+ ba,a,pt %xcc, 5b
+ENDPROC(sha1_sparc64_transform)
diff --git a/arch/sparc/crypto/sha1_glue.c b/arch/sparc/crypto/sha1_glue.c
new file mode 100644
index 00000000000..6cd5f29e1e0
--- /dev/null
+++ b/arch/sparc/crypto/sha1_glue.c
@@ -0,0 +1,185 @@
+/* Glue code for SHA1 hashing optimized for sparc64 crypto opcodes.
+ *
+ * This is based largely upon arch/x86/crypto/sha1_ssse3_glue.c
+ *
+ * Copyright (c) Alan Smithee.
+ * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
+ * Copyright (c) Jean-Francois Dive <jef@linuxbe.org>
+ * Copyright (c) Mathias Krause <minipli@googlemail.com>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <crypto/internal/hash.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/cryptohash.h>
+#include <linux/types.h>
+#include <crypto/sha.h>
+
+#include <asm/pstate.h>
+#include <asm/elf.h>
+
+#include "opcodes.h"
+
+asmlinkage void sha1_sparc64_transform(u32 *digest, const char *data,
+ unsigned int rounds);
+
+static int sha1_sparc64_init(struct shash_desc *desc)
+{
+ struct sha1_state *sctx = shash_desc_ctx(desc);
+
+ *sctx = (struct sha1_state){
+ .state = { SHA1_H0, SHA1_H1, SHA1_H2, SHA1_H3, SHA1_H4 },
+ };
+
+ return 0;
+}
+
+static void __sha1_sparc64_update(struct sha1_state *sctx, const u8 *data,
+ unsigned int len, unsigned int partial)
+{
+ unsigned int done = 0;
+
+ sctx->count += len;
+ if (partial) {
+ done = SHA1_BLOCK_SIZE - partial;
+ memcpy(sctx->buffer + partial, data, done);
+ sha1_sparc64_transform(sctx->state, sctx->buffer, 1);
+ }
+ if (len - done >= SHA1_BLOCK_SIZE) {
+ const unsigned int rounds = (len - done) / SHA1_BLOCK_SIZE;
+
+ sha1_sparc64_transform(sctx->state, data + done, rounds);
+ done += rounds * SHA1_BLOCK_SIZE;
+ }
+
+ memcpy(sctx->buffer, data + done, len - done);
+}
+
+static int sha1_sparc64_update(struct shash_desc *desc, const u8 *data,
+ unsigned int len)
+{
+ struct sha1_state *sctx = shash_desc_ctx(desc);
+ unsigned int partial = sctx->count % SHA1_BLOCK_SIZE;
+
+ /* Handle the fast case right here */
+ if (partial + len < SHA1_BLOCK_SIZE) {
+ sctx->count += len;
+ memcpy(sctx->buffer + partial, data, len);
+ } else
+ __sha1_sparc64_update(sctx, data, len, partial);
+
+ return 0;
+}
+
+/* Add padding and return the message digest. */
+static int sha1_sparc64_final(struct shash_desc *desc, u8 *out)
+{
+ struct sha1_state *sctx = shash_desc_ctx(desc);
+ unsigned int i, index, padlen;
+ __be32 *dst = (__be32 *)out;
+ __be64 bits;
+ static const u8 padding[SHA1_BLOCK_SIZE] = { 0x80, };
+
+ bits = cpu_to_be64(sctx->count << 3);
+
+ /* Pad out to 56 mod 64 and append length */
+ index = sctx->count % SHA1_BLOCK_SIZE;
+ padlen = (index < 56) ? (56 - index) : ((SHA1_BLOCK_SIZE+56) - index);
+
+ /* We need to fill a whole block for __sha1_sparc64_update() */
+ if (padlen <= 56) {
+ sctx->count += padlen;
+ memcpy(sctx->buffer + index, padding, padlen);
+ } else {
+ __sha1_sparc64_update(sctx, padding, padlen, index);
+ }
+ __sha1_sparc64_update(sctx, (const u8 *)&bits, sizeof(bits), 56);
+
+ /* Store state in digest */
+ for (i = 0; i < 5; i++)
+ dst[i] = cpu_to_be32(sctx->state[i]);
+
+ /* Wipe context */
+ memset(sctx, 0, sizeof(*sctx));
+
+ return 0;
+}
+
+static int sha1_sparc64_export(struct shash_desc *desc, void *out)
+{
+ struct sha1_state *sctx = shash_desc_ctx(desc);
+
+ memcpy(out, sctx, sizeof(*sctx));
+
+ return 0;
+}
+
+static int sha1_sparc64_import(struct shash_desc *desc, const void *in)
+{
+ struct sha1_state *sctx = shash_desc_ctx(desc);
+
+ memcpy(sctx, in, sizeof(*sctx));
+
+ return 0;
+}
+
+static struct shash_alg alg = {
+ .digestsize = SHA1_DIGEST_SIZE,
+ .init = sha1_sparc64_init,
+ .update = sha1_sparc64_update,
+ .final = sha1_sparc64_final,
+ .export = sha1_sparc64_export,
+ .import = sha1_sparc64_import,
+ .descsize = sizeof(struct sha1_state),
+ .statesize = sizeof(struct sha1_state),
+ .base = {
+ .cra_name = "sha1",
+ .cra_driver_name= "sha1-sparc64",
+ .cra_priority = SPARC_CR_OPCODE_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_SHASH,
+ .cra_blocksize = SHA1_BLOCK_SIZE,
+ .cra_module = THIS_MODULE,
+ }
+};
+
+static bool __init sparc64_has_sha1_opcode(void)
+{
+ unsigned long cfr;
+
+ if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO))
+ return false;
+
+ __asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr));
+ if (!(cfr & CFR_SHA1))
+ return false;
+
+ return true;
+}
+
+static int __init sha1_sparc64_mod_init(void)
+{
+ if (sparc64_has_sha1_opcode()) {
+ pr_info("Using sparc64 sha1 opcode optimized SHA-1 implementation\n");
+ return crypto_register_shash(&alg);
+ }
+ pr_info("sparc64 sha1 opcode not available.\n");
+ return -ENODEV;
+}
+
+static void __exit sha1_sparc64_mod_fini(void)
+{
+ crypto_unregister_shash(&alg);
+}
+
+module_init(sha1_sparc64_mod_init);
+module_exit(sha1_sparc64_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm, sparc64 sha1 opcode accelerated");
+
+MODULE_ALIAS("sha1");
+
+#include "crop_devid.c"
diff --git a/arch/sparc/crypto/sha256_asm.S b/arch/sparc/crypto/sha256_asm.S
new file mode 100644
index 00000000000..b5f3d5826eb
--- /dev/null
+++ b/arch/sparc/crypto/sha256_asm.S
@@ -0,0 +1,78 @@
+#include <linux/linkage.h>
+#include <asm/visasm.h>
+
+#include "opcodes.h"
+
+ENTRY(sha256_sparc64_transform)
+ /* %o0 = digest, %o1 = data, %o2 = rounds */
+ VISEntryHalf
+ ld [%o0 + 0x00], %f0
+ ld [%o0 + 0x04], %f1
+ ld [%o0 + 0x08], %f2
+ ld [%o0 + 0x0c], %f3
+ ld [%o0 + 0x10], %f4
+ ld [%o0 + 0x14], %f5
+ andcc %o1, 0x7, %g0
+ ld [%o0 + 0x18], %f6
+ bne,pn %xcc, 10f
+ ld [%o0 + 0x1c], %f7
+
+1:
+ ldd [%o1 + 0x00], %f8
+ ldd [%o1 + 0x08], %f10
+ ldd [%o1 + 0x10], %f12
+ ldd [%o1 + 0x18], %f14
+ ldd [%o1 + 0x20], %f16
+ ldd [%o1 + 0x28], %f18
+ ldd [%o1 + 0x30], %f20
+ ldd [%o1 + 0x38], %f22
+
+ SHA256
+
+ subcc %o2, 1, %o2
+ bne,pt %xcc, 1b
+ add %o1, 0x40, %o1
+
+5:
+ st %f0, [%o0 + 0x00]
+ st %f1, [%o0 + 0x04]
+ st %f2, [%o0 + 0x08]
+ st %f3, [%o0 + 0x0c]
+ st %f4, [%o0 + 0x10]
+ st %f5, [%o0 + 0x14]
+ st %f6, [%o0 + 0x18]
+ st %f7, [%o0 + 0x1c]
+ retl
+ VISExitHalf
+10:
+ alignaddr %o1, %g0, %o1
+
+ ldd [%o1 + 0x00], %f10
+1:
+ ldd [%o1 + 0x08], %f12
+ ldd [%o1 + 0x10], %f14
+ ldd [%o1 + 0x18], %f16
+ ldd [%o1 + 0x20], %f18
+ ldd [%o1 + 0x28], %f20
+ ldd [%o1 + 0x30], %f22
+ ldd [%o1 + 0x38], %f24
+ ldd [%o1 + 0x40], %f26
+
+ faligndata %f10, %f12, %f8
+ faligndata %f12, %f14, %f10
+ faligndata %f14, %f16, %f12
+ faligndata %f16, %f18, %f14
+ faligndata %f18, %f20, %f16
+ faligndata %f20, %f22, %f18
+ faligndata %f22, %f24, %f20
+ faligndata %f24, %f26, %f22
+
+ SHA256
+
+ subcc %o2, 1, %o2
+ fsrc2 %f26, %f10
+ bne,pt %xcc, 1b
+ add %o1, 0x40, %o1
+
+ ba,a,pt %xcc, 5b
+ENDPROC(sha256_sparc64_transform)
diff --git a/arch/sparc/crypto/sha256_glue.c b/arch/sparc/crypto/sha256_glue.c
new file mode 100644
index 00000000000..04f555ab268
--- /dev/null
+++ b/arch/sparc/crypto/sha256_glue.c
@@ -0,0 +1,243 @@
+/* Glue code for SHA256 hashing optimized for sparc64 crypto opcodes.
+ *
+ * This is based largely upon crypto/sha256_generic.c
+ *
+ * Copyright (c) Jean-Luc Cooke <jlcooke@certainkey.com>
+ * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ * SHA224 Support Copyright 2007 Intel Corporation <jonathan.lynch@intel.com>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <crypto/internal/hash.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/cryptohash.h>
+#include <linux/types.h>
+#include <crypto/sha.h>
+
+#include <asm/pstate.h>
+#include <asm/elf.h>
+
+#include "opcodes.h"
+
+asmlinkage void sha256_sparc64_transform(u32 *digest, const char *data,
+ unsigned int rounds);
+
+static int sha224_sparc64_init(struct shash_desc *desc)
+{
+ struct sha256_state *sctx = shash_desc_ctx(desc);
+ sctx->state[0] = SHA224_H0;
+ sctx->state[1] = SHA224_H1;
+ sctx->state[2] = SHA224_H2;
+ sctx->state[3] = SHA224_H3;
+ sctx->state[4] = SHA224_H4;
+ sctx->state[5] = SHA224_H5;
+ sctx->state[6] = SHA224_H6;
+ sctx->state[7] = SHA224_H7;
+ sctx->count = 0;
+
+ return 0;
+}
+
+static int sha256_sparc64_init(struct shash_desc *desc)
+{
+ struct sha256_state *sctx = shash_desc_ctx(desc);
+ sctx->state[0] = SHA256_H0;
+ sctx->state[1] = SHA256_H1;
+ sctx->state[2] = SHA256_H2;
+ sctx->state[3] = SHA256_H3;
+ sctx->state[4] = SHA256_H4;
+ sctx->state[5] = SHA256_H5;
+ sctx->state[6] = SHA256_H6;
+ sctx->state[7] = SHA256_H7;
+ sctx->count = 0;
+
+ return 0;
+}
+
+static void __sha256_sparc64_update(struct sha256_state *sctx, const u8 *data,
+ unsigned int len, unsigned int partial)
+{
+ unsigned int done = 0;
+
+ sctx->count += len;
+ if (partial) {
+ done = SHA256_BLOCK_SIZE - partial;
+ memcpy(sctx->buf + partial, data, done);
+ sha256_sparc64_transform(sctx->state, sctx->buf, 1);
+ }
+ if (len - done >= SHA256_BLOCK_SIZE) {
+ const unsigned int rounds = (len - done) / SHA256_BLOCK_SIZE;
+
+ sha256_sparc64_transform(sctx->state, data + done, rounds);
+ done += rounds * SHA256_BLOCK_SIZE;
+ }
+
+ memcpy(sctx->buf, data + done, len - done);
+}
+
+static int sha256_sparc64_update(struct shash_desc *desc, const u8 *data,
+ unsigned int len)
+{
+ struct sha256_state *sctx = shash_desc_ctx(desc);
+ unsigned int partial = sctx->count % SHA256_BLOCK_SIZE;
+
+ /* Handle the fast case right here */
+ if (partial + len < SHA256_BLOCK_SIZE) {
+ sctx->count += len;
+ memcpy(sctx->buf + partial, data, len);
+ } else
+ __sha256_sparc64_update(sctx, data, len, partial);
+
+ return 0;
+}
+
+static int sha256_sparc64_final(struct shash_desc *desc, u8 *out)
+{
+ struct sha256_state *sctx = shash_desc_ctx(desc);
+ unsigned int i, index, padlen;
+ __be32 *dst = (__be32 *)out;
+ __be64 bits;
+ static const u8 padding[SHA256_BLOCK_SIZE] = { 0x80, };
+
+ bits = cpu_to_be64(sctx->count << 3);
+
+ /* Pad out to 56 mod 64 and append length */
+ index = sctx->count % SHA256_BLOCK_SIZE;
+ padlen = (index < 56) ? (56 - index) : ((SHA256_BLOCK_SIZE+56) - index);
+
+ /* We need to fill a whole block for __sha256_sparc64_update() */
+ if (padlen <= 56) {
+ sctx->count += padlen;
+ memcpy(sctx->buf + index, padding, padlen);
+ } else {
+ __sha256_sparc64_update(sctx, padding, padlen, index);
+ }
+ __sha256_sparc64_update(sctx, (const u8 *)&bits, sizeof(bits), 56);
+
+ /* Store state in digest */
+ for (i = 0; i < 8; i++)
+ dst[i] = cpu_to_be32(sctx->state[i]);
+
+ /* Wipe context */
+ memset(sctx, 0, sizeof(*sctx));
+
+ return 0;
+}
+
+static int sha224_sparc64_final(struct shash_desc *desc, u8 *hash)
+{
+ u8 D[SHA256_DIGEST_SIZE];
+
+ sha256_sparc64_final(desc, D);
+
+ memcpy(hash, D, SHA224_DIGEST_SIZE);
+ memset(D, 0, SHA256_DIGEST_SIZE);
+
+ return 0;
+}
+
+static int sha256_sparc64_export(struct shash_desc *desc, void *out)
+{
+ struct sha256_state *sctx = shash_desc_ctx(desc);
+
+ memcpy(out, sctx, sizeof(*sctx));
+ return 0;
+}
+
+static int sha256_sparc64_import(struct shash_desc *desc, const void *in)
+{
+ struct sha256_state *sctx = shash_desc_ctx(desc);
+
+ memcpy(sctx, in, sizeof(*sctx));
+ return 0;
+}
+
+static struct shash_alg sha256 = {
+ .digestsize = SHA256_DIGEST_SIZE,
+ .init = sha256_sparc64_init,
+ .update = sha256_sparc64_update,
+ .final = sha256_sparc64_final,
+ .export = sha256_sparc64_export,
+ .import = sha256_sparc64_import,
+ .descsize = sizeof(struct sha256_state),
+ .statesize = sizeof(struct sha256_state),
+ .base = {
+ .cra_name = "sha256",
+ .cra_driver_name= "sha256-sparc64",
+ .cra_priority = SPARC_CR_OPCODE_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_SHASH,
+ .cra_blocksize = SHA256_BLOCK_SIZE,
+ .cra_module = THIS_MODULE,
+ }
+};
+
+static struct shash_alg sha224 = {
+ .digestsize = SHA224_DIGEST_SIZE,
+ .init = sha224_sparc64_init,
+ .update = sha256_sparc64_update,
+ .final = sha224_sparc64_final,
+ .descsize = sizeof(struct sha256_state),
+ .base = {
+ .cra_name = "sha224",
+ .cra_driver_name= "sha224-sparc64",
+ .cra_priority = SPARC_CR_OPCODE_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_SHASH,
+ .cra_blocksize = SHA224_BLOCK_SIZE,
+ .cra_module = THIS_MODULE,
+ }
+};
+
+static bool __init sparc64_has_sha256_opcode(void)
+{
+ unsigned long cfr;
+
+ if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO))
+ return false;
+
+ __asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr));
+ if (!(cfr & CFR_SHA256))
+ return false;
+
+ return true;
+}
+
+static int __init sha256_sparc64_mod_init(void)
+{
+ if (sparc64_has_sha256_opcode()) {
+ int ret = crypto_register_shash(&sha224);
+ if (ret < 0)
+ return ret;
+
+ ret = crypto_register_shash(&sha256);
+ if (ret < 0) {
+ crypto_unregister_shash(&sha224);
+ return ret;
+ }
+
+ pr_info("Using sparc64 sha256 opcode optimized SHA-256/SHA-224 implementation\n");
+ return 0;
+ }
+ pr_info("sparc64 sha256 opcode not available.\n");
+ return -ENODEV;
+}
+
+static void __exit sha256_sparc64_mod_fini(void)
+{
+ crypto_unregister_shash(&sha224);
+ crypto_unregister_shash(&sha256);
+}
+
+module_init(sha256_sparc64_mod_init);
+module_exit(sha256_sparc64_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("SHA-224 and SHA-256 Secure Hash Algorithm, sparc64 sha256 opcode accelerated");
+
+MODULE_ALIAS("sha224");
+MODULE_ALIAS("sha256");
+
+#include "crop_devid.c"
diff --git a/arch/sparc/crypto/sha512_asm.S b/arch/sparc/crypto/sha512_asm.S
new file mode 100644
index 00000000000..54bfba713c0
--- /dev/null
+++ b/arch/sparc/crypto/sha512_asm.S
@@ -0,0 +1,102 @@
+#include <linux/linkage.h>
+#include <asm/visasm.h>
+
+#include "opcodes.h"
+
+ENTRY(sha512_sparc64_transform)
+ /* %o0 = digest, %o1 = data, %o2 = rounds */
+ VISEntry
+ ldd [%o0 + 0x00], %f0
+ ldd [%o0 + 0x08], %f2
+ ldd [%o0 + 0x10], %f4
+ ldd [%o0 + 0x18], %f6
+ ldd [%o0 + 0x20], %f8
+ ldd [%o0 + 0x28], %f10
+ andcc %o1, 0x7, %g0
+ ldd [%o0 + 0x30], %f12
+ bne,pn %xcc, 10f
+ ldd [%o0 + 0x38], %f14
+
+1:
+ ldd [%o1 + 0x00], %f16
+ ldd [%o1 + 0x08], %f18
+ ldd [%o1 + 0x10], %f20
+ ldd [%o1 + 0x18], %f22
+ ldd [%o1 + 0x20], %f24
+ ldd [%o1 + 0x28], %f26
+ ldd [%o1 + 0x30], %f28
+ ldd [%o1 + 0x38], %f30
+ ldd [%o1 + 0x40], %f32
+ ldd [%o1 + 0x48], %f34
+ ldd [%o1 + 0x50], %f36
+ ldd [%o1 + 0x58], %f38
+ ldd [%o1 + 0x60], %f40
+ ldd [%o1 + 0x68], %f42
+ ldd [%o1 + 0x70], %f44
+ ldd [%o1 + 0x78], %f46
+
+ SHA512
+
+ subcc %o2, 1, %o2
+ bne,pt %xcc, 1b
+ add %o1, 0x80, %o1
+
+5:
+ std %f0, [%o0 + 0x00]
+ std %f2, [%o0 + 0x08]
+ std %f4, [%o0 + 0x10]
+ std %f6, [%o0 + 0x18]
+ std %f8, [%o0 + 0x20]
+ std %f10, [%o0 + 0x28]
+ std %f12, [%o0 + 0x30]
+ std %f14, [%o0 + 0x38]
+ retl
+ VISExit
+10:
+ alignaddr %o1, %g0, %o1
+
+ ldd [%o1 + 0x00], %f18
+1:
+ ldd [%o1 + 0x08], %f20
+ ldd [%o1 + 0x10], %f22
+ ldd [%o1 + 0x18], %f24
+ ldd [%o1 + 0x20], %f26
+ ldd [%o1 + 0x28], %f28
+ ldd [%o1 + 0x30], %f30
+ ldd [%o1 + 0x38], %f32
+ ldd [%o1 + 0x40], %f34
+ ldd [%o1 + 0x48], %f36
+ ldd [%o1 + 0x50], %f38
+ ldd [%o1 + 0x58], %f40
+ ldd [%o1 + 0x60], %f42
+ ldd [%o1 + 0x68], %f44
+ ldd [%o1 + 0x70], %f46
+ ldd [%o1 + 0x78], %f48
+ ldd [%o1 + 0x80], %f50
+
+ faligndata %f18, %f20, %f16
+ faligndata %f20, %f22, %f18
+ faligndata %f22, %f24, %f20
+ faligndata %f24, %f26, %f22
+ faligndata %f26, %f28, %f24
+ faligndata %f28, %f30, %f26
+ faligndata %f30, %f32, %f28
+ faligndata %f32, %f34, %f30
+ faligndata %f34, %f36, %f32
+ faligndata %f36, %f38, %f34
+ faligndata %f38, %f40, %f36
+ faligndata %f40, %f42, %f38
+ faligndata %f42, %f44, %f40
+ faligndata %f44, %f46, %f42
+ faligndata %f46, %f48, %f44
+ faligndata %f48, %f50, %f46
+
+ SHA512
+
+ subcc %o2, 1, %o2
+ fsrc2 %f50, %f18
+ bne,pt %xcc, 1b
+ add %o1, 0x80, %o1
+
+ ba,a,pt %xcc, 5b
+ENDPROC(sha512_sparc64_transform)
diff --git a/arch/sparc/crypto/sha512_glue.c b/arch/sparc/crypto/sha512_glue.c
new file mode 100644
index 00000000000..f04d1994d19
--- /dev/null
+++ b/arch/sparc/crypto/sha512_glue.c
@@ -0,0 +1,228 @@
+/* Glue code for SHA512 hashing optimized for sparc64 crypto opcodes.
+ *
+ * This is based largely upon crypto/sha512_generic.c
+ *
+ * Copyright (c) Jean-Luc Cooke <jlcooke@certainkey.com>
+ * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
+ * Copyright (c) 2003 Kyle McMartin <kyle@debian.org>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <crypto/internal/hash.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/cryptohash.h>
+#include <linux/types.h>
+#include <crypto/sha.h>
+
+#include <asm/pstate.h>
+#include <asm/elf.h>
+
+#include "opcodes.h"
+
+asmlinkage void sha512_sparc64_transform(u64 *digest, const char *data,
+ unsigned int rounds);
+
+static int sha512_sparc64_init(struct shash_desc *desc)
+{
+ struct sha512_state *sctx = shash_desc_ctx(desc);
+ sctx->state[0] = SHA512_H0;
+ sctx->state[1] = SHA512_H1;
+ sctx->state[2] = SHA512_H2;
+ sctx->state[3] = SHA512_H3;
+ sctx->state[4] = SHA512_H4;
+ sctx->state[5] = SHA512_H5;
+ sctx->state[6] = SHA512_H6;
+ sctx->state[7] = SHA512_H7;
+ sctx->count[0] = sctx->count[1] = 0;
+
+ return 0;
+}
+
+static int sha384_sparc64_init(struct shash_desc *desc)
+{
+ struct sha512_state *sctx = shash_desc_ctx(desc);
+ sctx->state[0] = SHA384_H0;
+ sctx->state[1] = SHA384_H1;
+ sctx->state[2] = SHA384_H2;
+ sctx->state[3] = SHA384_H3;
+ sctx->state[4] = SHA384_H4;
+ sctx->state[5] = SHA384_H5;
+ sctx->state[6] = SHA384_H6;
+ sctx->state[7] = SHA384_H7;
+ sctx->count[0] = sctx->count[1] = 0;
+
+ return 0;
+}
+
+static void __sha512_sparc64_update(struct sha512_state *sctx, const u8 *data,
+ unsigned int len, unsigned int partial)
+{
+ unsigned int done = 0;
+
+ if ((sctx->count[0] += len) < len)
+ sctx->count[1]++;
+ if (partial) {
+ done = SHA512_BLOCK_SIZE - partial;
+ memcpy(sctx->buf + partial, data, done);
+ sha512_sparc64_transform(sctx->state, sctx->buf, 1);
+ }
+ if (len - done >= SHA512_BLOCK_SIZE) {
+ const unsigned int rounds = (len - done) / SHA512_BLOCK_SIZE;
+
+ sha512_sparc64_transform(sctx->state, data + done, rounds);
+ done += rounds * SHA512_BLOCK_SIZE;
+ }
+
+ memcpy(sctx->buf, data + done, len - done);
+}
+
+static int sha512_sparc64_update(struct shash_desc *desc, const u8 *data,
+ unsigned int len)
+{
+ struct sha512_state *sctx = shash_desc_ctx(desc);
+ unsigned int partial = sctx->count[0] % SHA512_BLOCK_SIZE;
+
+ /* Handle the fast case right here */
+ if (partial + len < SHA512_BLOCK_SIZE) {
+ if ((sctx->count[0] += len) < len)
+ sctx->count[1]++;
+ memcpy(sctx->buf + partial, data, len);
+ } else
+ __sha512_sparc64_update(sctx, data, len, partial);
+
+ return 0;
+}
+
+static int sha512_sparc64_final(struct shash_desc *desc, u8 *out)
+{
+ struct sha512_state *sctx = shash_desc_ctx(desc);
+ unsigned int i, index, padlen;
+ __be64 *dst = (__be64 *)out;
+ __be64 bits[2];
+ static const u8 padding[SHA512_BLOCK_SIZE] = { 0x80, };
+
+ /* Save number of bits */
+ bits[1] = cpu_to_be64(sctx->count[0] << 3);
+ bits[0] = cpu_to_be64(sctx->count[1] << 3 | sctx->count[0] >> 61);
+
+ /* Pad out to 112 mod 128 and append length */
+ index = sctx->count[0] % SHA512_BLOCK_SIZE;
+ padlen = (index < 112) ? (112 - index) : ((SHA512_BLOCK_SIZE+112) - index);
+
+ /* We need to fill a whole block for __sha512_sparc64_update() */
+ if (padlen <= 112) {
+ if ((sctx->count[0] += padlen) < padlen)
+ sctx->count[1]++;
+ memcpy(sctx->buf + index, padding, padlen);
+ } else {
+ __sha512_sparc64_update(sctx, padding, padlen, index);
+ }
+ __sha512_sparc64_update(sctx, (const u8 *)&bits, sizeof(bits), 112);
+
+ /* Store state in digest */
+ for (i = 0; i < 8; i++)
+ dst[i] = cpu_to_be64(sctx->state[i]);
+
+ /* Wipe context */
+ memset(sctx, 0, sizeof(*sctx));
+
+ return 0;
+}
+
+static int sha384_sparc64_final(struct shash_desc *desc, u8 *hash)
+{
+ u8 D[64];
+
+ sha512_sparc64_final(desc, D);
+
+ memcpy(hash, D, 48);
+ memset(D, 0, 64);
+
+ return 0;
+}
+
+static struct shash_alg sha512 = {
+ .digestsize = SHA512_DIGEST_SIZE,
+ .init = sha512_sparc64_init,
+ .update = sha512_sparc64_update,
+ .final = sha512_sparc64_final,
+ .descsize = sizeof(struct sha512_state),
+ .base = {
+ .cra_name = "sha512",
+ .cra_driver_name= "sha512-sparc64",
+ .cra_priority = SPARC_CR_OPCODE_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_SHASH,
+ .cra_blocksize = SHA512_BLOCK_SIZE,
+ .cra_module = THIS_MODULE,
+ }
+};
+
+static struct shash_alg sha384 = {
+ .digestsize = SHA384_DIGEST_SIZE,
+ .init = sha384_sparc64_init,
+ .update = sha512_sparc64_update,
+ .final = sha384_sparc64_final,
+ .descsize = sizeof(struct sha512_state),
+ .base = {
+ .cra_name = "sha384",
+ .cra_driver_name= "sha384-sparc64",
+ .cra_priority = SPARC_CR_OPCODE_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_SHASH,
+ .cra_blocksize = SHA384_BLOCK_SIZE,
+ .cra_module = THIS_MODULE,
+ }
+};
+
+static bool __init sparc64_has_sha512_opcode(void)
+{
+ unsigned long cfr;
+
+ if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO))
+ return false;
+
+ __asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr));
+ if (!(cfr & CFR_SHA512))
+ return false;
+
+ return true;
+}
+
+static int __init sha512_sparc64_mod_init(void)
+{
+ if (sparc64_has_sha512_opcode()) {
+ int ret = crypto_register_shash(&sha384);
+ if (ret < 0)
+ return ret;
+
+ ret = crypto_register_shash(&sha512);
+ if (ret < 0) {
+ crypto_unregister_shash(&sha384);
+ return ret;
+ }
+
+ pr_info("Using sparc64 sha512 opcode optimized SHA-512/SHA-384 implementation\n");
+ return 0;
+ }
+ pr_info("sparc64 sha512 opcode not available.\n");
+ return -ENODEV;
+}
+
+static void __exit sha512_sparc64_mod_fini(void)
+{
+ crypto_unregister_shash(&sha384);
+ crypto_unregister_shash(&sha512);
+}
+
+module_init(sha512_sparc64_mod_init);
+module_exit(sha512_sparc64_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("SHA-384 and SHA-512 Secure Hash Algorithm, sparc64 sha512 opcode accelerated");
+
+MODULE_ALIAS("sha384");
+MODULE_ALIAS("sha512");
+
+#include "crop_devid.c"
diff --git a/arch/sparc/defconfig b/arch/sparc/defconfig
deleted file mode 100644
index 79e54894529..00000000000
--- a/arch/sparc/defconfig
+++ /dev/null
@@ -1,997 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc1
-# Sun Dec 17 14:20:47 2006
-#
-CONFIG_MMU=y
-CONFIG_HIGHMEM=y
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-CONFIG_LOCALVERSION_AUTO=y
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
-CONFIG_POSIX_MQUEUE=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
-# CONFIG_AUDIT is not set
-# CONFIG_IKCONFIG is not set
-CONFIG_SYSFS_DEPRECATED=y
-# CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
-# CONFIG_EMBEDDED is not set
-CONFIG_UID16=y
-CONFIG_SYSCTL_SYSCALL=y
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_ALL is not set
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_HOTPLUG=y
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_SHMEM=y
-CONFIG_SLAB=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-# CONFIG_MODVERSIONS is not set
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
-
-#
-# Block layer
-#
-CONFIG_BLOCK=y
-# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_DEFAULT_AS is not set
-# CONFIG_DEFAULT_DEADLINE is not set
-CONFIG_DEFAULT_CFQ=y
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="cfq"
-
-#
-# General machine setup
-#
-# CONFIG_SMP is not set
-CONFIG_SPARC=y
-CONFIG_SPARC32=y
-CONFIG_SBUS=y
-CONFIG_SBUSCHAR=y
-CONFIG_SERIAL_CONSOLE=y
-CONFIG_SUN_AUXIO=y
-CONFIG_SUN_IO=y
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_GENERIC_FIND_NEXT_BIT=y
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
-CONFIG_SUN_PM=y
-# CONFIG_SUN4 is not set
-CONFIG_PCI=y
-# CONFIG_PCI_MULTITHREAD_PROBE is not set
-# CONFIG_PCI_DEBUG is not set
-CONFIG_SUN_OPENPROMFS=m
-# CONFIG_SPARC_LED is not set
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_AOUT=y
-CONFIG_BINFMT_MISC=m
-CONFIG_SUNOS_EMUL=y
-CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
-# CONFIG_DISCONTIGMEM_MANUAL is not set
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
-
-#
-# Networking
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_NETDEBUG is not set
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-# CONFIG_XFRM_SUB_POLICY is not set
-CONFIG_NET_KEY=m
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-CONFIG_INET_AH=y
-CONFIG_INET_ESP=y
-CONFIG_INET_IPCOMP=y
-CONFIG_INET_XFRM_TUNNEL=y
-CONFIG_INET_TUNNEL=y
-CONFIG_INET_XFRM_MODE_TRANSPORT=y
-CONFIG_INET_XFRM_MODE_TUNNEL=y
-CONFIG_INET_XFRM_MODE_BEET=y
-CONFIG_INET_DIAG=y
-CONFIG_INET_TCP_DIAG=y
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_CUBIC=y
-CONFIG_DEFAULT_TCP_CONG="cubic"
-# CONFIG_TCP_MD5SIG is not set
-CONFIG_IPV6=m
-CONFIG_IPV6_PRIVACY=y
-# CONFIG_IPV6_ROUTER_PREF is not set
-CONFIG_INET6_AH=m
-CONFIG_INET6_ESP=m
-CONFIG_INET6_IPCOMP=m
-# CONFIG_IPV6_MIP6 is not set
-CONFIG_INET6_XFRM_TUNNEL=m
-CONFIG_INET6_TUNNEL=m
-CONFIG_INET6_XFRM_MODE_TRANSPORT=m
-CONFIG_INET6_XFRM_MODE_TUNNEL=m
-CONFIG_INET6_XFRM_MODE_BEET=m
-# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
-CONFIG_IPV6_SIT=m
-CONFIG_IPV6_TUNNEL=m
-# CONFIG_IPV6_MULTIPLE_TABLES is not set
-# CONFIG_NETWORK_SECMARK is not set
-# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IP_SCTP=m
-# CONFIG_SCTP_DBG_MSG is not set
-CONFIG_SCTP_DBG_OBJCNT=y
-# CONFIG_SCTP_HMAC_NONE is not set
-# CONFIG_SCTP_HMAC_SHA1 is not set
-CONFIG_SCTP_HMAC_MD5=y
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-CONFIG_NET_PKTGEN=m
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-# CONFIG_IEEE80211 is not set
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-# CONFIG_DEBUG_DRIVER is not set
-# CONFIG_SYS_HYPERVISOR is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
-# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-CONFIG_BLK_DEV_LOOP=m
-CONFIG_BLK_DEV_CRYPTOLOOP=m
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_SX8 is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CDROM_PKTCDVD is not set
-# CONFIG_ATA_OVER_ETH is not set
-
-#
-# Misc devices
-#
-# CONFIG_SGI_IOC4 is not set
-# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_RAID_ATTRS is not set
-CONFIG_SCSI=y
-# CONFIG_SCSI_TGT is not set
-# CONFIG_SCSI_NETLINK is not set
-CONFIG_SCSI_PROC_FS=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-# CONFIG_CHR_DEV_ST is not set
-# CONFIG_CHR_DEV_OSST is not set
-CONFIG_BLK_DEV_SR=m
-# CONFIG_BLK_DEV_SR_VENDOR is not set
-CONFIG_CHR_DEV_SG=m
-# CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-# CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_CONSTANTS is not set
-# CONFIG_SCSI_LOGGING is not set
-# CONFIG_SCSI_SCAN_ASYNC is not set
-
-#
-# SCSI Transports
-#
-CONFIG_SCSI_SPI_ATTRS=m
-# CONFIG_SCSI_FC_ATTRS is not set
-# CONFIG_SCSI_ISCSI_ATTRS is not set
-# CONFIG_SCSI_SAS_ATTRS is not set
-# CONFIG_SCSI_SAS_LIBSAS is not set
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_ISCSI_TCP is not set
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_3W_9XXX is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AACRAID is not set
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_AIC94XX is not set
-# CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_SCSI_ARCMSR is not set
-# CONFIG_MEGARAID_NEWGEN is not set
-# CONFIG_MEGARAID_LEGACY is not set
-# CONFIG_MEGARAID_SAS is not set
-# CONFIG_SCSI_HPTIOP is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_STEX is not set
-# CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-CONFIG_SCSI_QLOGICPTI=m
-# CONFIG_SCSI_QLA_FC is not set
-# CONFIG_SCSI_QLA_ISCSI is not set
-# CONFIG_SCSI_LPFC is not set
-# CONFIG_SCSI_DC395x is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_NSP32 is not set
-# CONFIG_SCSI_DEBUG is not set
-CONFIG_SCSI_SUNESP=y
-# CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
-# CONFIG_ATA is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-# CONFIG_FUSION_SPI is not set
-# CONFIG_FUSION_FC is not set
-# CONFIG_FUSION_SAS is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-CONFIG_DUMMY=m
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-CONFIG_TUN=m
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
-# CONFIG_PHYLIB is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=m
-CONFIG_SUNLANCE=y
-CONFIG_HAPPYMEAL=m
-CONFIG_SUNBMAC=m
-CONFIG_SUNQE=m
-# CONFIG_SUNGEM is not set
-# CONFIG_CASSINI is not set
-# CONFIG_NET_VENDOR_3COM is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_MYRI_SBUS is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-# CONFIG_QLA3XXX is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_CHELSIO_T1 is not set
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-# CONFIG_MYRI10GE is not set
-# CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-# CONFIG_NET_FC is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-CONFIG_INPUT_JOYDEV=m
-# CONFIG_INPUT_TSDEV is not set
-CONFIG_INPUT_EVDEV=m
-CONFIG_INPUT_EVBUG=m
-
-#
-# Input Device Drivers
-#
-CONFIG_INPUT_KEYBOARD=y
-CONFIG_KEYBOARD_ATKBD=m
-CONFIG_KEYBOARD_SUNKBD=m
-# CONFIG_KEYBOARD_LKKBD is not set
-# CONFIG_KEYBOARD_XTKBD is not set
-# CONFIG_KEYBOARD_NEWTON is not set
-# CONFIG_KEYBOARD_STOWAWAY is not set
-CONFIG_INPUT_MOUSE=y
-CONFIG_MOUSE_PS2=m
-CONFIG_MOUSE_SERIAL=m
-# CONFIG_MOUSE_VSXXXAA is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Hardware I/O ports
-#
-CONFIG_SERIO=m
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=m
-# CONFIG_SERIO_PCIPS2 is not set
-CONFIG_SERIO_LIBPS2=m
-# CONFIG_SERIO_RAW is not set
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-# CONFIG_VT_HW_CONSOLE_BINDING is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_SUNCORE=y
-CONFIG_SERIAL_SUNZILOG=y
-CONFIG_SERIAL_SUNZILOG_CONSOLE=y
-CONFIG_SERIAL_SUNSU=y
-CONFIG_SERIAL_SUNSU_CONSOLE=y
-# CONFIG_SERIAL_SUNSAB is not set
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_JSM is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-CONFIG_HW_RANDOM=m
-CONFIG_RTC=m
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# SPI support
-#
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
-
-#
-# Dallas's 1-wire bus
-#
-# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
-CONFIG_HWMON=y
-# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ABITUGURU is not set
-# CONFIG_SENSORS_F71805F is not set
-# CONFIG_SENSORS_PC87427 is not set
-# CONFIG_SENSORS_VT1211 is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-CONFIG_FIRMWARE_EDID=y
-# CONFIG_FB is not set
-
-#
-# Console display driver support
-#
-# CONFIG_PROM_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# HID Devices
-#
-CONFIG_HID=y
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-CONFIG_USB_ARCH_HAS_EHCI=y
-# CONFIG_USB is not set
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# LED devices
-#
-# CONFIG_NEW_LEDS is not set
-
-#
-# LED drivers
-#
-
-#
-# LED Triggers
-#
-
-#
-# InfiniBand support
-#
-# CONFIG_INFINIBAND is not set
-
-#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
-#
-
-#
-# Real Time Clock
-#
-# CONFIG_RTC_CLASS is not set
-
-#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
-# Virtualization
-#
-
-#
-# Misc Linux/SPARC drivers
-#
-CONFIG_SUN_OPENPROMIO=m
-CONFIG_SUN_MOSTEK_RTC=m
-# CONFIG_SUN_BPP is not set
-# CONFIG_SUN_VIDEOPIX is not set
-# CONFIG_TADPOLE_TS102_UCTRL is not set
-# CONFIG_SUN_JSFLASH is not set
-
-#
-# Unix98 PTY support
-#
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_POSIX_ACL=y
-CONFIG_EXT2_FS_SECURITY=y
-# CONFIG_EXT2_FS_XIP is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_FS is not set
-CONFIG_FS_MBCACHE=y
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
-CONFIG_XFS_FS=m
-CONFIG_XFS_QUOTA=y
-CONFIG_XFS_SECURITY=y
-CONFIG_XFS_POSIX_ACL=y
-CONFIG_XFS_RT=y
-# CONFIG_GFS2_FS is not set
-# CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-CONFIG_ROMFS_FS=m
-CONFIG_INOTIFY=y
-CONFIG_INOTIFY_USER=y
-# CONFIG_QUOTA is not set
-CONFIG_QUOTACTL=y
-CONFIG_DNOTIFY=y
-CONFIG_AUTOFS_FS=m
-CONFIG_AUTOFS4_FS=m
-# CONFIG_FUSE_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-CONFIG_ISO9660_FS=m
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_PROC_SYSCTL=y
-CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-CONFIG_BEFS_FS=m
-# CONFIG_BEFS_DEBUG is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-# CONFIG_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-CONFIG_SUNRPC_GSS=m
-CONFIG_RPCSEC_GSS_KRB5=m
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
-CONFIG_CIFS=m
-# CONFIG_CIFS_STATS is not set
-# CONFIG_CIFS_WEAK_PW_HASH is not set
-# CONFIG_CIFS_XATTR is not set
-# CONFIG_CIFS_DEBUG2 is not set
-# CONFIG_CIFS_EXPERIMENTAL is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-CONFIG_AFS_FS=m
-CONFIG_RXRPC=m
-# CONFIG_9P_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-CONFIG_SUN_PARTITION=y
-
-#
-# Native Language Support
-#
-CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ASCII is not set
-# CONFIG_NLS_ISO8859_1 is not set
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
-
-#
-# Distributed Lock Manager
-#
-# CONFIG_DLM is not set
-
-#
-# Instrumentation Support
-#
-# CONFIG_PROFILING is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_PRINTK_TIME is not set
-CONFIG_ENABLE_MUST_CHECK=y
-CONFIG_MAGIC_SYSRQ=y
-# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
-# CONFIG_HEADERS_CHECK is not set
-CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_DETECT_SOFTLOCKUP=y
-# CONFIG_SCHEDSTATS is not set
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_RT_MUTEXES is not set
-# CONFIG_RT_MUTEX_TESTER is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_MUTEXES is not set
-# CONFIG_DEBUG_RWSEMS is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
-# CONFIG_DEBUG_KOBJECT is not set
-# CONFIG_DEBUG_HIGHMEM is not set
-CONFIG_DEBUG_BUGVERBOSE=y
-# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_VM is not set
-# CONFIG_DEBUG_LIST is not set
-CONFIG_FORCED_INLINING=y
-# CONFIG_RCU_TORTURE_TEST is not set
-# CONFIG_DEBUG_STACK_USAGE is not set
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=y
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_HMAC=y
-# CONFIG_CRYPTO_XCBC is not set
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=y
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_SHA1=y
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-# CONFIG_CRYPTO_WP512 is not set
-# CONFIG_CRYPTO_TGR192 is not set
-# CONFIG_CRYPTO_GF128MUL is not set
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_CBC=y
-# CONFIG_CRYPTO_LRW is not set
-CONFIG_CRYPTO_DES=y
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_TWOFISH_COMMON=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-# CONFIG_CRYPTO_TEA is not set
-CONFIG_CRYPTO_ARC4=m
-# CONFIG_CRYPTO_KHAZAD is not set
-# CONFIG_CRYPTO_ANUBIS is not set
-CONFIG_CRYPTO_DEFLATE=y
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=m
-# CONFIG_CRYPTO_TEST is not set
-
-#
-# Hardware crypto devices
-#
-
-#
-# Library routines
-#
-CONFIG_BITREVERSE=y
-# CONFIG_CRC_CCITT is not set
-# CONFIG_CRC16 is not set
-CONFIG_CRC32=y
-CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
new file mode 100644
index 00000000000..a4582181800
--- /dev/null
+++ b/arch/sparc/include/asm/Kbuild
@@ -0,0 +1,21 @@
+# User exported sparc header files
+
+
+generic-y += clkdev.h
+generic-y += cputime.h
+generic-y += div64.h
+generic-y += emergency-restart.h
+generic-y += exec.h
+generic-y += hash.h
+generic-y += irq_regs.h
+generic-y += linkage.h
+generic-y += local.h
+generic-y += local64.h
+generic-y += mcs_spinlock.h
+generic-y += module.h
+generic-y += mutex.h
+generic-y += preempt.h
+generic-y += serial.h
+generic-y += trace_clock.h
+generic-y += types.h
+generic-y += word-at-a-time.h
diff --git a/arch/sparc/include/asm/agp.h b/arch/sparc/include/asm/agp.h
new file mode 100644
index 00000000000..70f52c1661b
--- /dev/null
+++ b/arch/sparc/include/asm/agp.h
@@ -0,0 +1,16 @@
+#ifndef AGP_H
+#define AGP_H 1
+
+/* dummy for now */
+
+#define map_page_into_agp(page)
+#define unmap_page_from_agp(page)
+#define flush_agp_cache() mb()
+
+/* GATT allocation. Returns/accepts GATT kernel virtual address. */
+#define alloc_gatt_pages(order) \
+ ((char *)__get_free_pages(GFP_KERNEL, (order)))
+#define free_gatt_pages(table, order) \
+ free_pages((unsigned long)(table), (order))
+
+#endif
diff --git a/arch/sparc/include/asm/apb.h b/arch/sparc/include/asm/apb.h
new file mode 100644
index 00000000000..8f3b57db810
--- /dev/null
+++ b/arch/sparc/include/asm/apb.h
@@ -0,0 +1,36 @@
+/*
+ * apb.h: Advanced PCI Bridge Configuration Registers and Bits
+ *
+ * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
+ */
+
+#ifndef _SPARC64_APB_H
+#define _SPARC64_APB_H
+
+#define APB_TICK_REGISTER 0xb0
+#define APB_INT_ACK 0xb8
+#define APB_PRIMARY_MASTER_RETRY_LIMIT 0xc0
+#define APB_DMA_ASFR 0xc8
+#define APB_DMA_AFAR 0xd0
+#define APB_PIO_TARGET_RETRY_LIMIT 0xd8
+#define APB_PIO_TARGET_LATENCY_TIMER 0xd9
+#define APB_DMA_TARGET_RETRY_LIMIT 0xda
+#define APB_DMA_TARGET_LATENCY_TIMER 0xdb
+#define APB_SECONDARY_MASTER_RETRY_LIMIT 0xdc
+#define APB_SECONDARY_CONTROL 0xdd
+#define APB_IO_ADDRESS_MAP 0xde
+#define APB_MEM_ADDRESS_MAP 0xdf
+
+#define APB_PCI_CONTROL_LOW 0xe0
+# define APB_PCI_CTL_LOW_ARB_PARK (1 << 21)
+# define APB_PCI_CTL_LOW_ERRINT_EN (1 << 8)
+
+#define APB_PCI_CONTROL_HIGH 0xe4
+# define APB_PCI_CTL_HIGH_SERR (1 << 2)
+# define APB_PCI_CTL_HIGH_ARBITER_EN (1 << 0)
+
+#define APB_PIO_ASFR 0xe8
+#define APB_PIO_AFAR 0xf0
+#define APB_DIAG_REGISTER 0xf8
+
+#endif /* !(_SPARC64_APB_H) */
diff --git a/arch/sparc/include/asm/asm-offsets.h b/arch/sparc/include/asm/asm-offsets.h
new file mode 100644
index 00000000000..d370ee36a18
--- /dev/null
+++ b/arch/sparc/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/sparc/include/asm/asm.h b/arch/sparc/include/asm/asm.h
new file mode 100644
index 00000000000..e8e1d94b4cc
--- /dev/null
+++ b/arch/sparc/include/asm/asm.h
@@ -0,0 +1,40 @@
+#ifndef _SPARC_ASM_H
+#define _SPARC_ASM_H
+
+/* Macros to assist the sharing of assembler code between 32-bit and
+ * 64-bit sparc.
+ */
+
+#ifdef CONFIG_SPARC64
+#define BRANCH32(TYPE, PREDICT, DEST) \
+ TYPE,PREDICT %icc, DEST
+#define BRANCH32_ANNUL(TYPE, PREDICT, DEST) \
+ TYPE,a,PREDICT %icc, DEST
+#define BRANCH_REG_ZERO(PREDICT, REG, DEST) \
+ brz,PREDICT REG, DEST
+#define BRANCH_REG_ZERO_ANNUL(PREDICT, REG, DEST) \
+ brz,a,PREDICT REG, DEST
+#define BRANCH_REG_NOT_ZERO(PREDICT, REG, DEST) \
+ brnz,PREDICT REG, DEST
+#define BRANCH_REG_NOT_ZERO_ANNUL(PREDICT, REG, DEST) \
+ brnz,a,PREDICT REG, DEST
+#else
+#define BRANCH32(TYPE, PREDICT, DEST) \
+ TYPE DEST
+#define BRANCH32_ANNUL(TYPE, PREDICT, DEST) \
+ TYPE,a DEST
+#define BRANCH_REG_ZERO(PREDICT, REG, DEST) \
+ cmp REG, 0; \
+ be DEST
+#define BRANCH_REG_ZERO_ANNUL(PREDICT, REG, DEST) \
+ cmp REG, 0; \
+ be,a DEST
+#define BRANCH_REG_NOT_ZERO(PREDICT, REG, DEST) \
+ cmp REG, 0; \
+ bne DEST
+#define BRANCH_REG_NOT_ZERO_ANNUL(PREDICT, REG, DEST) \
+ cmp REG, 0; \
+ bne,a DEST
+#endif
+
+#endif /* _SPARC_ASM_H */
diff --git a/arch/sparc/include/asm/asmmacro.h b/arch/sparc/include/asm/asmmacro.h
new file mode 100644
index 00000000000..a0e28ef0255
--- /dev/null
+++ b/arch/sparc/include/asm/asmmacro.h
@@ -0,0 +1,45 @@
+/* asmmacro.h: Assembler macros.
+ *
+ * Copyright (C) 1996 David S. Miller (davem@caipfs.rutgers.edu)
+ */
+
+#ifndef _SPARC_ASMMACRO_H
+#define _SPARC_ASMMACRO_H
+
+/* All trap entry points _must_ begin with this macro or else you
+ * lose. It makes sure the kernel has a proper window so that
+ * c-code can be called.
+ */
+#define SAVE_ALL_HEAD \
+ sethi %hi(trap_setup), %l4; \
+ jmpl %l4 + %lo(trap_setup), %l6;
+#define SAVE_ALL \
+ SAVE_ALL_HEAD \
+ nop;
+
+/* All traps low-level code here must end with this macro. */
+#define RESTORE_ALL b ret_trap_entry; clr %l6;
+
+/* Support for run-time patching of single instructions.
+ * This is used to handle the differences in the ASI for
+ * MMUREGS for LEON and SUN.
+ *
+ * Sample:
+ * LEON_PI(lda [%g0] ASI_LEON_MMUREGS, %o0
+ * SUN_PI_(lda [%g0] ASI_M_MMUREGS, %o0
+ * PI == Patch Instruction
+ *
+ * For LEON we will use the first variant,
+ * and for all other we will use the SUN variant.
+ * The order is important.
+ */
+#define LEON_PI(...) \
+662: __VA_ARGS__
+
+#define SUN_PI_(...) \
+ .section .leon_1insn_patch, "ax"; \
+ .word 662b; \
+ __VA_ARGS__; \
+ .previous
+
+#endif /* !(_SPARC_ASMMACRO_H) */
diff --git a/arch/sparc/include/asm/atomic.h b/arch/sparc/include/asm/atomic.h
new file mode 100644
index 00000000000..8ff83d8cc33
--- /dev/null
+++ b/arch/sparc/include/asm/atomic.h
@@ -0,0 +1,8 @@
+#ifndef ___ASM_SPARC_ATOMIC_H
+#define ___ASM_SPARC_ATOMIC_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/atomic_64.h>
+#else
+#include <asm/atomic_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/atomic_32.h b/arch/sparc/include/asm/atomic_32.h
new file mode 100644
index 00000000000..7aed2be45b4
--- /dev/null
+++ b/arch/sparc/include/asm/atomic_32.h
@@ -0,0 +1,56 @@
+/* atomic.h: These still suck, but the I-cache hit rate is higher.
+ *
+ * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com.au)
+ * Copyright (C) 2007 Kyle McMartin (kyle@parisc-linux.org)
+ *
+ * Additions by Keith M Wesolowski (wesolows@foobazco.org) based
+ * on asm-parisc/atomic.h Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>.
+ */
+
+#ifndef __ARCH_SPARC_ATOMIC__
+#define __ARCH_SPARC_ATOMIC__
+
+#include <linux/types.h>
+
+#include <asm/cmpxchg.h>
+#include <asm/barrier.h>
+#include <asm-generic/atomic64.h>
+
+
+#define ATOMIC_INIT(i) { (i) }
+
+int __atomic_add_return(int, atomic_t *);
+int atomic_cmpxchg(atomic_t *, int, int);
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
+int __atomic_add_unless(atomic_t *, int, int);
+void atomic_set(atomic_t *, int);
+
+#define atomic_read(v) (*(volatile int *)&(v)->counter)
+
+#define atomic_add(i, v) ((void)__atomic_add_return( (int)(i), (v)))
+#define atomic_sub(i, v) ((void)__atomic_add_return(-(int)(i), (v)))
+#define atomic_inc(v) ((void)__atomic_add_return( 1, (v)))
+#define atomic_dec(v) ((void)__atomic_add_return( -1, (v)))
+
+#define atomic_add_return(i, v) (__atomic_add_return( (int)(i), (v)))
+#define atomic_sub_return(i, v) (__atomic_add_return(-(int)(i), (v)))
+#define atomic_inc_return(v) (__atomic_add_return( 1, (v)))
+#define atomic_dec_return(v) (__atomic_add_return( -1, (v)))
+
+#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0)
+
+/*
+ * atomic_inc_and_test - increment and test
+ * @v: pointer of type atomic_t
+ *
+ * Atomically increments @v by 1
+ * and returns true if the result is zero, or false for all
+ * other cases.
+ */
+#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
+
+#define atomic_dec_and_test(v) (atomic_dec_return(v) == 0)
+#define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0)
+
+#endif /* !(__ARCH_SPARC_ATOMIC__) */
diff --git a/arch/sparc/include/asm/atomic_64.h b/arch/sparc/include/asm/atomic_64.h
new file mode 100644
index 00000000000..bb894c8bec5
--- /dev/null
+++ b/arch/sparc/include/asm/atomic_64.h
@@ -0,0 +1,112 @@
+/* atomic.h: Thankfully the V9 is at least reasonable for this
+ * stuff.
+ *
+ * Copyright (C) 1996, 1997, 2000, 2012 David S. Miller (davem@redhat.com)
+ */
+
+#ifndef __ARCH_SPARC64_ATOMIC__
+#define __ARCH_SPARC64_ATOMIC__
+
+#include <linux/types.h>
+#include <asm/cmpxchg.h>
+#include <asm/barrier.h>
+
+#define ATOMIC_INIT(i) { (i) }
+#define ATOMIC64_INIT(i) { (i) }
+
+#define atomic_read(v) (*(volatile int *)&(v)->counter)
+#define atomic64_read(v) (*(volatile long *)&(v)->counter)
+
+#define atomic_set(v, i) (((v)->counter) = i)
+#define atomic64_set(v, i) (((v)->counter) = i)
+
+void atomic_add(int, atomic_t *);
+void atomic64_add(long, atomic64_t *);
+void atomic_sub(int, atomic_t *);
+void atomic64_sub(long, atomic64_t *);
+
+int atomic_add_ret(int, atomic_t *);
+long atomic64_add_ret(long, atomic64_t *);
+int atomic_sub_ret(int, atomic_t *);
+long atomic64_sub_ret(long, atomic64_t *);
+
+#define atomic_dec_return(v) atomic_sub_ret(1, v)
+#define atomic64_dec_return(v) atomic64_sub_ret(1, v)
+
+#define atomic_inc_return(v) atomic_add_ret(1, v)
+#define atomic64_inc_return(v) atomic64_add_ret(1, v)
+
+#define atomic_sub_return(i, v) atomic_sub_ret(i, v)
+#define atomic64_sub_return(i, v) atomic64_sub_ret(i, v)
+
+#define atomic_add_return(i, v) atomic_add_ret(i, v)
+#define atomic64_add_return(i, v) atomic64_add_ret(i, v)
+
+/*
+ * atomic_inc_and_test - increment and test
+ * @v: pointer of type atomic_t
+ *
+ * Atomically increments @v by 1
+ * and returns true if the result is zero, or false for all
+ * other cases.
+ */
+#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
+#define atomic64_inc_and_test(v) (atomic64_inc_return(v) == 0)
+
+#define atomic_sub_and_test(i, v) (atomic_sub_ret(i, v) == 0)
+#define atomic64_sub_and_test(i, v) (atomic64_sub_ret(i, v) == 0)
+
+#define atomic_dec_and_test(v) (atomic_sub_ret(1, v) == 0)
+#define atomic64_dec_and_test(v) (atomic64_sub_ret(1, v) == 0)
+
+#define atomic_inc(v) atomic_add(1, v)
+#define atomic64_inc(v) atomic64_add(1, v)
+
+#define atomic_dec(v) atomic_sub(1, v)
+#define atomic64_dec(v) atomic64_sub(1, v)
+
+#define atomic_add_negative(i, v) (atomic_add_ret(i, v) < 0)
+#define atomic64_add_negative(i, v) (atomic64_add_ret(i, v) < 0)
+
+#define atomic_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n)))
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
+
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
+{
+ int c, old;
+ c = atomic_read(v);
+ for (;;) {
+ if (unlikely(c == (u)))
+ break;
+ old = atomic_cmpxchg((v), c, c + (a));
+ if (likely(old == c))
+ break;
+ c = old;
+ }
+ return c;
+}
+
+#define atomic64_cmpxchg(v, o, n) \
+ ((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n)))
+#define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
+
+static inline long atomic64_add_unless(atomic64_t *v, long a, long u)
+{
+ long c, old;
+ c = atomic64_read(v);
+ for (;;) {
+ if (unlikely(c == (u)))
+ break;
+ old = atomic64_cmpxchg((v), c, c + (a));
+ if (likely(old == c))
+ break;
+ c = old;
+ }
+ return c != (u);
+}
+
+#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
+
+long atomic64_dec_if_positive(atomic64_t *v);
+
+#endif /* !(__ARCH_SPARC64_ATOMIC__) */
diff --git a/arch/sparc/include/asm/auxio.h b/arch/sparc/include/asm/auxio.h
new file mode 100644
index 00000000000..3e09a07b77e
--- /dev/null
+++ b/arch/sparc/include/asm/auxio.h
@@ -0,0 +1,15 @@
+#ifndef ___ASM_SPARC_AUXIO_H
+#define ___ASM_SPARC_AUXIO_H
+
+#ifndef __ASSEMBLY__
+
+extern void __iomem *auxio_register;
+
+#endif /* ifndef __ASSEMBLY__ */
+
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/auxio_64.h>
+#else
+#include <asm/auxio_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/auxio_32.h b/arch/sparc/include/asm/auxio_32.h
new file mode 100644
index 00000000000..5d685df427b
--- /dev/null
+++ b/arch/sparc/include/asm/auxio_32.h
@@ -0,0 +1,88 @@
+/*
+ * auxio.h: Definitions and code for the Auxiliary I/O register.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+#ifndef _SPARC_AUXIO_H
+#define _SPARC_AUXIO_H
+
+#include <asm/vaddrs.h>
+
+/* This register is an unsigned char in IO space. It does two things.
+ * First, it is used to control the front panel LED light on machines
+ * that have it (good for testing entry points to trap handlers and irq's)
+ * Secondly, it controls various floppy drive parameters.
+ */
+#define AUXIO_ORMEIN 0xf0 /* All writes must set these bits. */
+#define AUXIO_ORMEIN4M 0xc0 /* sun4m - All writes must set these bits. */
+#define AUXIO_FLPY_DENS 0x20 /* Floppy density, high if set. Read only. */
+#define AUXIO_FLPY_DCHG 0x10 /* A disk change occurred. Read only. */
+#define AUXIO_EDGE_ON 0x10 /* sun4m - On means Jumper block is in. */
+#define AUXIO_FLPY_DSEL 0x08 /* Drive select/start-motor. Write only. */
+#define AUXIO_LINK_TEST 0x08 /* sun4m - On means TPE Carrier detect. */
+
+/* Set the following to one, then zero, after doing a pseudo DMA transfer. */
+#define AUXIO_FLPY_TCNT 0x04 /* Floppy terminal count. Write only. */
+
+/* Set the following to zero to eject the floppy. */
+#define AUXIO_FLPY_EJCT 0x02 /* Eject floppy disk. Write only. */
+#define AUXIO_LED 0x01 /* On if set, off if unset. Read/Write */
+
+#ifndef __ASSEMBLY__
+
+/*
+ * NOTE: these routines are implementation dependent--
+ * understand the hardware you are querying!
+ */
+void set_auxio(unsigned char bits_on, unsigned char bits_off);
+unsigned char get_auxio(void); /* .../asm/floppy.h */
+
+/*
+ * The following routines are provided for driver-compatibility
+ * with sparc64 (primarily sunlance.c)
+ */
+
+#define AUXIO_LTE_ON 1
+#define AUXIO_LTE_OFF 0
+
+/* auxio_set_lte - Set Link Test Enable (TPE Link Detect)
+ *
+ * on - AUXIO_LTE_ON or AUXIO_LTE_OFF
+ */
+#define auxio_set_lte(on) \
+do { \
+ if(on) { \
+ set_auxio(AUXIO_LINK_TEST, 0); \
+ } else { \
+ set_auxio(0, AUXIO_LINK_TEST); \
+ } \
+} while (0)
+
+#define AUXIO_LED_ON 1
+#define AUXIO_LED_OFF 0
+
+/* auxio_set_led - Set system front panel LED
+ *
+ * on - AUXIO_LED_ON or AUXIO_LED_OFF
+ */
+#define auxio_set_led(on) \
+do { \
+ if(on) { \
+ set_auxio(AUXIO_LED, 0); \
+ } else { \
+ set_auxio(0, AUXIO_LED); \
+ } \
+} while (0)
+
+#endif /* !(__ASSEMBLY__) */
+
+
+/* AUXIO2 (Power Off Control) */
+extern volatile u8 __iomem *auxio_power_register;
+
+#define AUXIO_POWER_DETECT_FAILURE 32
+#define AUXIO_POWER_CLEAR_FAILURE 2
+#define AUXIO_POWER_OFF 1
+
+
+#endif /* !(_SPARC_AUXIO_H) */
diff --git a/arch/sparc/include/asm/auxio_64.h b/arch/sparc/include/asm/auxio_64.h
new file mode 100644
index 00000000000..6079e59a7ad
--- /dev/null
+++ b/arch/sparc/include/asm/auxio_64.h
@@ -0,0 +1,98 @@
+/*
+ * auxio.h: Definitions and code for the Auxiliary I/O registers.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ *
+ * Refactoring for unified NCR/PCIO support 2002 Eric Brower (ebrower@usa.net)
+ */
+#ifndef _SPARC64_AUXIO_H
+#define _SPARC64_AUXIO_H
+
+/* AUXIO implementations:
+ * sbus-based NCR89C105 "Slavio"
+ * LED/Floppy (AUX1) register
+ * Power (AUX2) register
+ *
+ * ebus-based auxio on PCIO
+ * LED Auxio Register
+ * Power Auxio Register
+ *
+ * Register definitions from NCR _NCR89C105 Chip Specification_
+ *
+ * SLAVIO AUX1 @ 0x1900000
+ * -------------------------------------------------
+ * | (R) | (R) | D | (R) | E | M | T | L |
+ * -------------------------------------------------
+ * (R) - bit 7:6,4 are reserved and should be masked in s/w
+ * D - Floppy Density Sense (1=high density) R/O
+ * E - Link Test Enable, directly reflected on AT&T 7213 LTE pin
+ * M - Monitor/Mouse Mux, directly reflected on MON_MSE_MUX pin
+ * T - Terminal Count: sends TC pulse to 82077 floppy controller
+ * L - System LED on front panel (0=off, 1=on)
+ */
+#define AUXIO_AUX1_MASK 0xc0 /* Mask bits */
+#define AUXIO_AUX1_FDENS 0x20 /* Floppy Density Sense */
+#define AUXIO_AUX1_LTE 0x08 /* Link Test Enable */
+#define AUXIO_AUX1_MMUX 0x04 /* Monitor/Mouse Mux */
+#define AUXIO_AUX1_FTCNT 0x02 /* Terminal Count, */
+#define AUXIO_AUX1_LED 0x01 /* System LED */
+
+/* SLAVIO AUX2 @ 0x1910000
+ * -------------------------------------------------
+ * | (R) | (R) | D | (R) | (R) | (R) | C | F |
+ * -------------------------------------------------
+ * (R) - bits 7:6,4:2 are reserved and should be masked in s/w
+ * D - Power Failure Detect (1=power fail)
+ * C - Clear Power Failure Detect Int (1=clear)
+ * F - Power Off (1=power off)
+ */
+#define AUXIO_AUX2_MASK 0xdc /* Mask Bits */
+#define AUXIO_AUX2_PFAILDET 0x20 /* Power Fail Detect */
+#define AUXIO_AUX2_PFAILCLR 0x02 /* Clear Pwr Fail Det Intr */
+#define AUXIO_AUX2_PWR_OFF 0x01 /* Power Off */
+
+/* Register definitions from Sun Microsystems _PCIO_ p/n 802-7837
+ *
+ * PCIO LED Auxio @ 0x726000
+ * -------------------------------------------------
+ * | 31:1 Unused | LED |
+ * -------------------------------------------------
+ * Bits 31:1 unused
+ * LED - System LED on front panel (0=off, 1=on)
+ */
+#define AUXIO_PCIO_LED 0x01 /* System LED */
+
+/* PCIO Power Auxio @ 0x724000
+ * -------------------------------------------------
+ * | 31:2 Unused | CPO | SPO |
+ * -------------------------------------------------
+ * Bits 31:2 unused
+ * CPO - Courtesy Power Off (1=off)
+ * SPO - System Power Off (1=off)
+ */
+#define AUXIO_PCIO_CPWR_OFF 0x02 /* Courtesy Power Off */
+#define AUXIO_PCIO_SPWR_OFF 0x01 /* System Power Off */
+
+#ifndef __ASSEMBLY__
+
+#define AUXIO_LTE_ON 1
+#define AUXIO_LTE_OFF 0
+
+/* auxio_set_lte - Set Link Test Enable (TPE Link Detect)
+ *
+ * on - AUXIO_LTE_ON or AUXIO_LTE_OFF
+ */
+void auxio_set_lte(int on);
+
+#define AUXIO_LED_ON 1
+#define AUXIO_LED_OFF 0
+
+/* auxio_set_led - Set system front panel LED
+ *
+ * on - AUXIO_LED_ON or AUXIO_LED_OFF
+ */
+void auxio_set_led(int on);
+
+#endif /* ifndef __ASSEMBLY__ */
+
+#endif /* !(_SPARC64_AUXIO_H) */
diff --git a/arch/sparc/include/asm/backoff.h b/arch/sparc/include/asm/backoff.h
new file mode 100644
index 00000000000..4e02086b839
--- /dev/null
+++ b/arch/sparc/include/asm/backoff.h
@@ -0,0 +1,85 @@
+#ifndef _SPARC64_BACKOFF_H
+#define _SPARC64_BACKOFF_H
+
+/* The macros in this file implement an exponential backoff facility
+ * for atomic operations.
+ *
+ * When multiple threads compete on an atomic operation, it is
+ * possible for one thread to be continually denied a successful
+ * completion of the compare-and-swap instruction. Heavily
+ * threaded cpu implementations like Niagara can compound this
+ * problem even further.
+ *
+ * When an atomic operation fails and needs to be retried, we spin a
+ * certain number of times. At each subsequent failure of the same
+ * operation we double the spin count, realizing an exponential
+ * backoff.
+ *
+ * When we spin, we try to use an operation that will cause the
+ * current cpu strand to block, and therefore make the core fully
+ * available to any other other runnable strands. There are two
+ * options, based upon cpu capabilities.
+ *
+ * On all cpus prior to SPARC-T4 we do three dummy reads of the
+ * condition code register. Each read blocks the strand for something
+ * between 40 and 50 cpu cycles.
+ *
+ * For SPARC-T4 and later we have a special "pause" instruction
+ * available. This is implemented using writes to register %asr27.
+ * The cpu will block the number of cycles written into the register,
+ * unless a disrupting trap happens first. SPARC-T4 specifically
+ * implements pause with a granularity of 8 cycles. Each strand has
+ * an internal pause counter which decrements every 8 cycles. So the
+ * chip shifts the %asr27 value down by 3 bits, and writes the result
+ * into the pause counter. If a value smaller than 8 is written, the
+ * chip blocks for 1 cycle.
+ *
+ * To achieve the same amount of backoff as the three %ccr reads give
+ * on earlier chips, we shift the backoff value up by 7 bits. (Three
+ * %ccr reads block for about 128 cycles, 1 << 7 == 128) We write the
+ * whole amount we want to block into the pause register, rather than
+ * loop writing 128 each time.
+ */
+
+#define BACKOFF_LIMIT (4 * 1024)
+
+#ifdef CONFIG_SMP
+
+#define BACKOFF_SETUP(reg) \
+ mov 1, reg
+
+#define BACKOFF_LABEL(spin_label, continue_label) \
+ spin_label
+
+#define BACKOFF_SPIN(reg, tmp, label) \
+ mov reg, tmp; \
+88: rd %ccr, %g0; \
+ rd %ccr, %g0; \
+ rd %ccr, %g0; \
+ .section .pause_3insn_patch,"ax";\
+ .word 88b; \
+ sllx tmp, 7, tmp; \
+ wr tmp, 0, %asr27; \
+ clr tmp; \
+ .previous; \
+ brnz,pt tmp, 88b; \
+ sub tmp, 1, tmp; \
+ set BACKOFF_LIMIT, tmp; \
+ cmp reg, tmp; \
+ bg,pn %xcc, label; \
+ nop; \
+ ba,pt %xcc, label; \
+ sllx reg, 1, reg;
+
+#else
+
+#define BACKOFF_SETUP(reg)
+
+#define BACKOFF_LABEL(spin_label, continue_label) \
+ continue_label
+
+#define BACKOFF_SPIN(reg, tmp, label)
+
+#endif
+
+#endif /* _SPARC64_BACKOFF_H */
diff --git a/arch/sparc/include/asm/barrier.h b/arch/sparc/include/asm/barrier.h
new file mode 100644
index 00000000000..b25f02a029e
--- /dev/null
+++ b/arch/sparc/include/asm/barrier.h
@@ -0,0 +1,8 @@
+#ifndef ___ASM_SPARC_BARRIER_H
+#define ___ASM_SPARC_BARRIER_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/barrier_64.h>
+#else
+#include <asm/barrier_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/barrier_32.h b/arch/sparc/include/asm/barrier_32.h
new file mode 100644
index 00000000000..ae69eda288f
--- /dev/null
+++ b/arch/sparc/include/asm/barrier_32.h
@@ -0,0 +1,7 @@
+#ifndef __SPARC_BARRIER_H
+#define __SPARC_BARRIER_H
+
+#include <asm/processor.h> /* for nop() */
+#include <asm-generic/barrier.h>
+
+#endif /* !(__SPARC_BARRIER_H) */
diff --git a/arch/sparc/include/asm/barrier_64.h b/arch/sparc/include/asm/barrier_64.h
new file mode 100644
index 00000000000..305dcc3dc72
--- /dev/null
+++ b/arch/sparc/include/asm/barrier_64.h
@@ -0,0 +1,74 @@
+#ifndef __SPARC64_BARRIER_H
+#define __SPARC64_BARRIER_H
+
+/* These are here in an effort to more fully work around Spitfire Errata
+ * #51. Essentially, if a memory barrier occurs soon after a mispredicted
+ * branch, the chip can stop executing instructions until a trap occurs.
+ * Therefore, if interrupts are disabled, the chip can hang forever.
+ *
+ * It used to be believed that the memory barrier had to be right in the
+ * delay slot, but a case has been traced recently wherein the memory barrier
+ * was one instruction after the branch delay slot and the chip still hung.
+ * The offending sequence was the following in sym_wakeup_done() of the
+ * sym53c8xx_2 driver:
+ *
+ * call sym_ccb_from_dsa, 0
+ * movge %icc, 0, %l0
+ * brz,pn %o0, .LL1303
+ * mov %o0, %l2
+ * membar #LoadLoad
+ *
+ * The branch has to be mispredicted for the bug to occur. Therefore, we put
+ * the memory barrier explicitly into a "branch always, predicted taken"
+ * delay slot to avoid the problem case.
+ */
+#define membar_safe(type) \
+do { __asm__ __volatile__("ba,pt %%xcc, 1f\n\t" \
+ " membar " type "\n" \
+ "1:\n" \
+ : : : "memory"); \
+} while (0)
+
+/* The kernel always executes in TSO memory model these days,
+ * and furthermore most sparc64 chips implement more stringent
+ * memory ordering than required by the specifications.
+ */
+#define mb() membar_safe("#StoreLoad")
+#define rmb() __asm__ __volatile__("":::"memory")
+#define wmb() __asm__ __volatile__("":::"memory")
+
+#define read_barrier_depends() do { } while(0)
+#define set_mb(__var, __value) \
+ do { __var = __value; membar_safe("#StoreLoad"); } while(0)
+
+#ifdef CONFIG_SMP
+#define smp_mb() mb()
+#define smp_rmb() rmb()
+#define smp_wmb() wmb()
+#else
+#define smp_mb() __asm__ __volatile__("":::"memory")
+#define smp_rmb() __asm__ __volatile__("":::"memory")
+#define smp_wmb() __asm__ __volatile__("":::"memory")
+#endif
+
+#define smp_read_barrier_depends() do { } while(0)
+
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ barrier(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(*p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ barrier(); \
+ ___p1; \
+})
+
+#define smp_mb__before_atomic() barrier()
+#define smp_mb__after_atomic() barrier()
+
+#endif /* !(__SPARC64_BARRIER_H) */
diff --git a/arch/sparc/include/asm/bbc.h b/arch/sparc/include/asm/bbc.h
new file mode 100644
index 00000000000..423a85800aa
--- /dev/null
+++ b/arch/sparc/include/asm/bbc.h
@@ -0,0 +1,225 @@
+/*
+ * bbc.h: Defines for BootBus Controller found on UltraSPARC-III
+ * systems.
+ *
+ * Copyright (C) 2000 David S. Miller (davem@redhat.com)
+ */
+
+#ifndef _SPARC64_BBC_H
+#define _SPARC64_BBC_H
+
+/* Register sizes are indicated by "B" (Byte, 1-byte),
+ * "H" (Half-word, 2 bytes), "W" (Word, 4 bytes) or
+ * "Q" (Quad, 8 bytes) inside brackets.
+ */
+
+#define BBC_AID 0x00 /* [B] Agent ID */
+#define BBC_DEVP 0x01 /* [B] Device Present */
+#define BBC_ARB 0x02 /* [B] Arbitration */
+#define BBC_QUIESCE 0x03 /* [B] Quiesce */
+#define BBC_WDACTION 0x04 /* [B] Watchdog Action */
+#define BBC_SPG 0x06 /* [B] Soft POR Gen */
+#define BBC_SXG 0x07 /* [B] Soft XIR Gen */
+#define BBC_PSRC 0x08 /* [W] POR Source */
+#define BBC_XSRC 0x0c /* [B] XIR Source */
+#define BBC_CSC 0x0d /* [B] Clock Synthesizers Control*/
+#define BBC_ES_CTRL 0x0e /* [H] Energy Star Control */
+#define BBC_ES_ACT 0x10 /* [W] E* Assert Change Time */
+#define BBC_ES_DACT 0x14 /* [B] E* De-Assert Change Time */
+#define BBC_ES_DABT 0x15 /* [B] E* De-Assert Bypass Time */
+#define BBC_ES_ABT 0x16 /* [H] E* Assert Bypass Time */
+#define BBC_ES_PST 0x18 /* [W] E* PLL Settle Time */
+#define BBC_ES_FSL 0x1c /* [W] E* Frequency Switch Latency*/
+#define BBC_EBUST 0x20 /* [Q] EBUS Timing */
+#define BBC_JTAG_CMD 0x28 /* [W] JTAG+ Command */
+#define BBC_JTAG_CTRL 0x2c /* [B] JTAG+ Control */
+#define BBC_I2C_SEL 0x2d /* [B] I2C Selection */
+#define BBC_I2C_0_S1 0x2e /* [B] I2C ctrlr-0 reg S1 */
+#define BBC_I2C_0_S0 0x2f /* [B] I2C ctrlr-0 regs S0,S0',S2,S3*/
+#define BBC_I2C_1_S1 0x30 /* [B] I2C ctrlr-1 reg S1 */
+#define BBC_I2C_1_S0 0x31 /* [B] I2C ctrlr-1 regs S0,S0',S2,S3*/
+#define BBC_KBD_BEEP 0x32 /* [B] Keyboard Beep */
+#define BBC_KBD_BCNT 0x34 /* [W] Keyboard Beep Counter */
+
+#define BBC_REGS_SIZE 0x40
+
+/* There is a 2K scratch ram area at offset 0x80000 but I doubt
+ * we will use it for anything.
+ */
+
+/* Agent ID register. This register shows the Safari Agent ID
+ * for the processors. The value returned depends upon which
+ * cpu is reading the register.
+ */
+#define BBC_AID_ID 0x07 /* Safari ID */
+#define BBC_AID_RESV 0xf8 /* Reserved */
+
+/* Device Present register. One can determine which cpus are actually
+ * present in the machine by interrogating this register.
+ */
+#define BBC_DEVP_CPU0 0x01 /* Processor 0 present */
+#define BBC_DEVP_CPU1 0x02 /* Processor 1 present */
+#define BBC_DEVP_CPU2 0x04 /* Processor 2 present */
+#define BBC_DEVP_CPU3 0x08 /* Processor 3 present */
+#define BBC_DEVP_RESV 0xf0 /* Reserved */
+
+/* Arbitration register. This register is used to block access to
+ * the BBC from a particular cpu.
+ */
+#define BBC_ARB_CPU0 0x01 /* Enable cpu 0 BBC arbitratrion */
+#define BBC_ARB_CPU1 0x02 /* Enable cpu 1 BBC arbitratrion */
+#define BBC_ARB_CPU2 0x04 /* Enable cpu 2 BBC arbitratrion */
+#define BBC_ARB_CPU3 0x08 /* Enable cpu 3 BBC arbitratrion */
+#define BBC_ARB_RESV 0xf0 /* Reserved */
+
+/* Quiesce register. Bus and BBC segments for cpus can be disabled
+ * with this register, ie. for hot plugging.
+ */
+#define BBC_QUIESCE_S02 0x01 /* Quiesce Safari segment for cpu 0 and 2 */
+#define BBC_QUIESCE_S13 0x02 /* Quiesce Safari segment for cpu 1 and 3 */
+#define BBC_QUIESCE_B02 0x04 /* Quiesce BBC segment for cpu 0 and 2 */
+#define BBC_QUIESCE_B13 0x08 /* Quiesce BBC segment for cpu 1 and 3 */
+#define BBC_QUIESCE_FD0 0x10 /* Disable Fatal_Error[0] reporting */
+#define BBC_QUIESCE_FD1 0x20 /* Disable Fatal_Error[1] reporting */
+#define BBC_QUIESCE_FD2 0x40 /* Disable Fatal_Error[2] reporting */
+#define BBC_QUIESCE_FD3 0x80 /* Disable Fatal_Error[3] reporting */
+
+/* Watchdog Action register. When the watchdog device timer expires
+ * a line is enabled to the BBC. The action BBC takes when this line
+ * is asserted can be controlled by this regiser.
+ */
+#define BBC_WDACTION_RST 0x01 /* When set, watchdog causes system reset.
+ * When clear, BBC ignores watchdog signal.
+ */
+#define BBC_WDACTION_RESV 0xfe /* Reserved */
+
+/* Soft_POR_GEN register. The POR (Power On Reset) signal may be asserted
+ * for specific processors or all processors via this register.
+ */
+#define BBC_SPG_CPU0 0x01 /* Assert POR for processor 0 */
+#define BBC_SPG_CPU1 0x02 /* Assert POR for processor 1 */
+#define BBC_SPG_CPU2 0x04 /* Assert POR for processor 2 */
+#define BBC_SPG_CPU3 0x08 /* Assert POR for processor 3 */
+#define BBC_SPG_CPUALL 0x10 /* Reset all processors and reset
+ * the entire system.
+ */
+#define BBC_SPG_RESV 0xe0 /* Reserved */
+
+/* Soft_XIR_GEN register. The XIR (eXternally Initiated Reset) signal
+ * may be asserted to specific processors via this register.
+ */
+#define BBC_SXG_CPU0 0x01 /* Assert XIR for processor 0 */
+#define BBC_SXG_CPU1 0x02 /* Assert XIR for processor 1 */
+#define BBC_SXG_CPU2 0x04 /* Assert XIR for processor 2 */
+#define BBC_SXG_CPU3 0x08 /* Assert XIR for processor 3 */
+#define BBC_SXG_RESV 0xf0 /* Reserved */
+
+/* POR Source register. One may identify the cause of the most recent
+ * reset by reading this register.
+ */
+#define BBC_PSRC_SPG0 0x0001 /* CPU 0 reset via BBC_SPG register */
+#define BBC_PSRC_SPG1 0x0002 /* CPU 1 reset via BBC_SPG register */
+#define BBC_PSRC_SPG2 0x0004 /* CPU 2 reset via BBC_SPG register */
+#define BBC_PSRC_SPG3 0x0008 /* CPU 3 reset via BBC_SPG register */
+#define BBC_PSRC_SPGSYS 0x0010 /* System reset via BBC_SPG register */
+#define BBC_PSRC_JTAG 0x0020 /* System reset via JTAG+ */
+#define BBC_PSRC_BUTTON 0x0040 /* System reset via push-button dongle */
+#define BBC_PSRC_PWRUP 0x0080 /* System reset via power-up */
+#define BBC_PSRC_FE0 0x0100 /* CPU 0 reported Fatal_Error */
+#define BBC_PSRC_FE1 0x0200 /* CPU 1 reported Fatal_Error */
+#define BBC_PSRC_FE2 0x0400 /* CPU 2 reported Fatal_Error */
+#define BBC_PSRC_FE3 0x0800 /* CPU 3 reported Fatal_Error */
+#define BBC_PSRC_FE4 0x1000 /* Schizo reported Fatal_Error */
+#define BBC_PSRC_FE5 0x2000 /* Safari device 5 reported Fatal_Error */
+#define BBC_PSRC_FE6 0x4000 /* CPMS reported Fatal_Error */
+#define BBC_PSRC_SYNTH 0x8000 /* System reset when on-board clock synthesizers
+ * were updated.
+ */
+#define BBC_PSRC_WDT 0x10000 /* System reset via Super I/O watchdog */
+#define BBC_PSRC_RSC 0x20000 /* System reset via RSC remote monitoring
+ * device
+ */
+
+/* XIR Source register. The source of an XIR event sent to a processor may
+ * be determined via this register.
+ */
+#define BBC_XSRC_SXG0 0x01 /* CPU 0 received XIR via Soft_XIR_GEN reg */
+#define BBC_XSRC_SXG1 0x02 /* CPU 1 received XIR via Soft_XIR_GEN reg */
+#define BBC_XSRC_SXG2 0x04 /* CPU 2 received XIR via Soft_XIR_GEN reg */
+#define BBC_XSRC_SXG3 0x08 /* CPU 3 received XIR via Soft_XIR_GEN reg */
+#define BBC_XSRC_JTAG 0x10 /* All CPUs received XIR via JTAG+ */
+#define BBC_XSRC_W_OR_B 0x20 /* All CPUs received XIR either because:
+ * a) Super I/O watchdog fired, or
+ * b) XIR push button was activated
+ */
+#define BBC_XSRC_RESV 0xc0 /* Reserved */
+
+/* Clock Synthesizers Control register. This register provides the big-bang
+ * programming interface to the two clock synthesizers of the machine.
+ */
+#define BBC_CSC_SLOAD 0x01 /* Directly connected to S_LOAD pins */
+#define BBC_CSC_SDATA 0x02 /* Directly connected to S_DATA pins */
+#define BBC_CSC_SCLOCK 0x04 /* Directly connected to S_CLOCK pins */
+#define BBC_CSC_RESV 0x78 /* Reserved */
+#define BBC_CSC_RST 0x80 /* Generate system reset when S_LOAD==1 */
+
+/* Energy Star Control register. This register is used to generate the
+ * clock frequency change trigger to the main system devices (Schizo and
+ * the processors). The transition occurs when bits in this register
+ * go from 0 to 1, only one bit must be set at once else no action
+ * occurs. Basically the sequence of events is:
+ * a) Choose new frequency: full, 1/2 or 1/32
+ * b) Program this desired frequency into the cpus and Schizo.
+ * c) Set the same value in this register.
+ * d) 16 system clocks later, clear this register.
+ */
+#define BBC_ES_CTRL_1_1 0x01 /* Full frequency */
+#define BBC_ES_CTRL_1_2 0x02 /* 1/2 frequency */
+#define BBC_ES_CTRL_1_32 0x20 /* 1/32 frequency */
+#define BBC_ES_RESV 0xdc /* Reserved */
+
+/* Energy Star Assert Change Time register. This determines the number
+ * of BBC clock cycles (which is half the system frequency) between
+ * the detection of FREEZE_ACK being asserted and the assertion of
+ * the CLK_CHANGE_L[2:0] signals.
+ */
+#define BBC_ES_ACT_VAL 0xff
+
+/* Energy Star Assert Bypass Time register. This determines the number
+ * of BBC clock cycles (which is half the system frequency) between
+ * the assertion of the CLK_CHANGE_L[2:0] signals and the assertion of
+ * the ESTAR_PLL_BYPASS signal.
+ */
+#define BBC_ES_ABT_VAL 0xffff
+
+/* Energy Star PLL Settle Time register. This determines the number of
+ * BBC clock cycles (which is half the system frequency) between the
+ * de-assertion of CLK_CHANGE_L[2:0] and the de-assertion of the FREEZE_L
+ * signal.
+ */
+#define BBC_ES_PST_VAL 0xffffffff
+
+/* Energy Star Frequency Switch Latency register. This is the number of
+ * BBC clocks between the de-assertion of CLK_CHANGE_L[2:0] and the first
+ * edge of the Safari clock at the new frequency.
+ */
+#define BBC_ES_FSL_VAL 0xffffffff
+
+/* Keyboard Beep control register. This is a simple enabler for the audio
+ * beep sound.
+ */
+#define BBC_KBD_BEEP_ENABLE 0x01 /* Enable beep */
+#define BBC_KBD_BEEP_RESV 0xfe /* Reserved */
+
+/* Keyboard Beep Counter register. There is a free-running counter inside
+ * the BBC which runs at half the system clock. The bit set in this register
+ * determines when the audio sound is generated. So for example if bit
+ * 10 is set, the audio beep will oscillate at 1/(2**12). The keyboard beep
+ * generator automatically selects a different bit to use if the system clock
+ * is changed via Energy Star.
+ */
+#define BBC_KBD_BCNT_BITS 0x0007fc00
+#define BBC_KBC_BCNT_RESV 0xfff803ff
+
+#endif /* _SPARC64_BBC_H */
+
diff --git a/arch/sparc/include/asm/bitext.h b/arch/sparc/include/asm/bitext.h
new file mode 100644
index 00000000000..9c988bf3adb
--- /dev/null
+++ b/arch/sparc/include/asm/bitext.h
@@ -0,0 +1,27 @@
+/*
+ * bitext.h: Bit string operations on the sparc, specific to architecture.
+ *
+ * Copyright 2002 Pete Zaitcev <zaitcev@yahoo.com>
+ */
+
+#ifndef _SPARC_BITEXT_H
+#define _SPARC_BITEXT_H
+
+#include <linux/spinlock.h>
+
+struct bit_map {
+ spinlock_t lock;
+ unsigned long *map;
+ int size;
+ int used;
+ int last_off;
+ int last_size;
+ int first_free;
+ int num_colors;
+};
+
+int bit_map_string_get(struct bit_map *t, int len, int align);
+void bit_map_clear(struct bit_map *t, int offset, int len);
+void bit_map_init(struct bit_map *t, unsigned long *map, int size);
+
+#endif /* defined(_SPARC_BITEXT_H) */
diff --git a/arch/sparc/include/asm/bitops.h b/arch/sparc/include/asm/bitops.h
new file mode 100644
index 00000000000..b1edd94bd64
--- /dev/null
+++ b/arch/sparc/include/asm/bitops.h
@@ -0,0 +1,8 @@
+#ifndef ___ASM_SPARC_BITOPS_H
+#define ___ASM_SPARC_BITOPS_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/bitops_64.h>
+#else
+#include <asm/bitops_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/bitops_32.h b/arch/sparc/include/asm/bitops_32.h
new file mode 100644
index 00000000000..600ed1d9c8c
--- /dev/null
+++ b/arch/sparc/include/asm/bitops_32.h
@@ -0,0 +1,108 @@
+/*
+ * bitops.h: Bit string operations on the Sparc.
+ *
+ * Copyright 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright 1996 Eddie C. Dost (ecd@skynet.be)
+ * Copyright 2001 Anton Blanchard (anton@samba.org)
+ */
+
+#ifndef _SPARC_BITOPS_H
+#define _SPARC_BITOPS_H
+
+#include <linux/compiler.h>
+#include <asm/byteorder.h>
+
+#ifdef __KERNEL__
+
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
+unsigned long ___set_bit(unsigned long *addr, unsigned long mask);
+unsigned long ___clear_bit(unsigned long *addr, unsigned long mask);
+unsigned long ___change_bit(unsigned long *addr, unsigned long mask);
+
+/*
+ * Set bit 'nr' in 32-bit quantity at address 'addr' where bit '0'
+ * is in the highest of the four bytes and bit '31' is the high bit
+ * within the first byte. Sparc is BIG-Endian. Unless noted otherwise
+ * all bit-ops return 0 if bit was previously clear and != 0 otherwise.
+ */
+static inline int test_and_set_bit(unsigned long nr, volatile unsigned long *addr)
+{
+ unsigned long *ADDR, mask;
+
+ ADDR = ((unsigned long *) addr) + (nr >> 5);
+ mask = 1 << (nr & 31);
+
+ return ___set_bit(ADDR, mask) != 0;
+}
+
+static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
+{
+ unsigned long *ADDR, mask;
+
+ ADDR = ((unsigned long *) addr) + (nr >> 5);
+ mask = 1 << (nr & 31);
+
+ (void) ___set_bit(ADDR, mask);
+}
+
+static inline int test_and_clear_bit(unsigned long nr, volatile unsigned long *addr)
+{
+ unsigned long *ADDR, mask;
+
+ ADDR = ((unsigned long *) addr) + (nr >> 5);
+ mask = 1 << (nr & 31);
+
+ return ___clear_bit(ADDR, mask) != 0;
+}
+
+static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
+{
+ unsigned long *ADDR, mask;
+
+ ADDR = ((unsigned long *) addr) + (nr >> 5);
+ mask = 1 << (nr & 31);
+
+ (void) ___clear_bit(ADDR, mask);
+}
+
+static inline int test_and_change_bit(unsigned long nr, volatile unsigned long *addr)
+{
+ unsigned long *ADDR, mask;
+
+ ADDR = ((unsigned long *) addr) + (nr >> 5);
+ mask = 1 << (nr & 31);
+
+ return ___change_bit(ADDR, mask) != 0;
+}
+
+static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
+{
+ unsigned long *ADDR, mask;
+
+ ADDR = ((unsigned long *) addr) + (nr >> 5);
+ mask = 1 << (nr & 31);
+
+ (void) ___change_bit(ADDR, mask);
+}
+
+#include <asm-generic/bitops/non-atomic.h>
+
+#include <asm-generic/bitops/ffz.h>
+#include <asm-generic/bitops/__ffs.h>
+#include <asm-generic/bitops/sched.h>
+#include <asm-generic/bitops/ffs.h>
+#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/__fls.h>
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/lock.h>
+#include <asm-generic/bitops/find.h>
+#include <asm-generic/bitops/le.h>
+#include <asm-generic/bitops/ext2-atomic.h>
+
+#endif /* __KERNEL__ */
+
+#endif /* defined(_SPARC_BITOPS_H) */
diff --git a/arch/sparc/include/asm/bitops_64.h b/arch/sparc/include/asm/bitops_64.h
new file mode 100644
index 00000000000..2d522402a93
--- /dev/null
+++ b/arch/sparc/include/asm/bitops_64.h
@@ -0,0 +1,63 @@
+/*
+ * bitops.h: Bit string operations on the V9.
+ *
+ * Copyright 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _SPARC64_BITOPS_H
+#define _SPARC64_BITOPS_H
+
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
+#include <linux/compiler.h>
+#include <asm/byteorder.h>
+#include <asm/barrier.h>
+
+int test_and_set_bit(unsigned long nr, volatile unsigned long *addr);
+int test_and_clear_bit(unsigned long nr, volatile unsigned long *addr);
+int test_and_change_bit(unsigned long nr, volatile unsigned long *addr);
+void set_bit(unsigned long nr, volatile unsigned long *addr);
+void clear_bit(unsigned long nr, volatile unsigned long *addr);
+void change_bit(unsigned long nr, volatile unsigned long *addr);
+
+#include <asm-generic/bitops/non-atomic.h>
+
+#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/__fls.h>
+#include <asm-generic/bitops/fls64.h>
+
+#ifdef __KERNEL__
+
+int ffs(int x);
+unsigned long __ffs(unsigned long);
+
+#include <asm-generic/bitops/ffz.h>
+#include <asm-generic/bitops/sched.h>
+
+/*
+ * hweightN: returns the hamming weight (i.e. the number
+ * of bits set) of a N-bit word
+ */
+
+unsigned long __arch_hweight64(__u64 w);
+unsigned int __arch_hweight32(unsigned int w);
+unsigned int __arch_hweight16(unsigned int w);
+unsigned int __arch_hweight8(unsigned int w);
+
+#include <asm-generic/bitops/const_hweight.h>
+#include <asm-generic/bitops/lock.h>
+#endif /* __KERNEL__ */
+
+#include <asm-generic/bitops/find.h>
+
+#ifdef __KERNEL__
+
+#include <asm-generic/bitops/le.h>
+
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
+
+#endif /* __KERNEL__ */
+
+#endif /* defined(_SPARC64_BITOPS_H) */
diff --git a/arch/sparc/include/asm/btext.h b/arch/sparc/include/asm/btext.h
new file mode 100644
index 00000000000..75a32b109e1
--- /dev/null
+++ b/arch/sparc/include/asm/btext.h
@@ -0,0 +1,6 @@
+#ifndef _SPARC_BTEXT_H
+#define _SPARC_BTEXT_H
+
+int btext_find_display(void);
+
+#endif /* _SPARC_BTEXT_H */
diff --git a/arch/sparc/include/asm/bug.h b/arch/sparc/include/asm/bug.h
new file mode 100644
index 00000000000..eaa8f8d3812
--- /dev/null
+++ b/arch/sparc/include/asm/bug.h
@@ -0,0 +1,25 @@
+#ifndef _SPARC_BUG_H
+#define _SPARC_BUG_H
+
+#ifdef CONFIG_BUG
+#include <linux/compiler.h>
+
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+void do_BUG(const char *file, int line);
+#define BUG() do { \
+ do_BUG(__FILE__, __LINE__); \
+ __builtin_trap(); \
+} while (0)
+#else
+#define BUG() __builtin_trap()
+#endif
+
+#define HAVE_ARCH_BUG
+#endif
+
+#include <asm-generic/bug.h>
+
+struct pt_regs;
+void __noreturn die_if_kernel(char *str, struct pt_regs *regs);
+
+#endif
diff --git a/arch/sparc/include/asm/bugs.h b/arch/sparc/include/asm/bugs.h
new file mode 100644
index 00000000000..61d86bbbe2b
--- /dev/null
+++ b/arch/sparc/include/asm/bugs.h
@@ -0,0 +1,17 @@
+/* include/asm/bugs.h: Sparc probes for various bugs.
+ *
+ * Copyright (C) 1996, 2007 David S. Miller (davem@davemloft.net)
+ */
+
+#ifdef CONFIG_SPARC32
+#include <asm/cpudata.h>
+#endif
+
+extern unsigned long loops_per_jiffy;
+
+static void __init check_bugs(void)
+{
+#if defined(CONFIG_SPARC32) && !defined(CONFIG_SMP)
+ cpu_data(0).udelay_val = loops_per_jiffy;
+#endif
+}
diff --git a/arch/sparc/include/asm/cache.h b/arch/sparc/include/asm/cache.h
new file mode 100644
index 00000000000..5bb6991b485
--- /dev/null
+++ b/arch/sparc/include/asm/cache.h
@@ -0,0 +1,25 @@
+/* cache.h: Cache specific code for the Sparc. These include flushing
+ * and direct tag/data line access.
+ *
+ * Copyright (C) 1995, 2007 David S. Miller (davem@davemloft.net)
+ */
+
+#ifndef _SPARC_CACHE_H
+#define _SPARC_CACHE_H
+
+#define ARCH_SLAB_MINALIGN __alignof__(unsigned long long)
+
+#define L1_CACHE_SHIFT 5
+#define L1_CACHE_BYTES 32
+
+#ifdef CONFIG_SPARC32
+#define SMP_CACHE_BYTES_SHIFT 5
+#else
+#define SMP_CACHE_BYTES_SHIFT 6
+#endif
+
+#define SMP_CACHE_BYTES (1 << SMP_CACHE_BYTES_SHIFT)
+
+#define __read_mostly __attribute__((__section__(".data..read_mostly")))
+
+#endif /* !(_SPARC_CACHE_H) */
diff --git a/arch/sparc/include/asm/cacheflush.h b/arch/sparc/include/asm/cacheflush.h
new file mode 100644
index 00000000000..f6c4839b838
--- /dev/null
+++ b/arch/sparc/include/asm/cacheflush.h
@@ -0,0 +1,12 @@
+#ifndef ___ASM_SPARC_CACHEFLUSH_H
+#define ___ASM_SPARC_CACHEFLUSH_H
+
+/* flush addr - to allow use of self-modifying code */
+#define flushi(addr) __asm__ __volatile__ ("flush %0" : : "r" (addr) : "memory")
+
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/cacheflush_64.h>
+#else
+#include <asm/cacheflush_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/cacheflush_32.h b/arch/sparc/include/asm/cacheflush_32.h
new file mode 100644
index 00000000000..12164006181
--- /dev/null
+++ b/arch/sparc/include/asm/cacheflush_32.h
@@ -0,0 +1,58 @@
+#ifndef _SPARC_CACHEFLUSH_H
+#define _SPARC_CACHEFLUSH_H
+
+#include <asm/cachetlb_32.h>
+
+#define flush_cache_all() \
+ sparc32_cachetlb_ops->cache_all()
+#define flush_cache_mm(mm) \
+ sparc32_cachetlb_ops->cache_mm(mm)
+#define flush_cache_dup_mm(mm) \
+ sparc32_cachetlb_ops->cache_mm(mm)
+#define flush_cache_range(vma,start,end) \
+ sparc32_cachetlb_ops->cache_range(vma, start, end)
+#define flush_cache_page(vma,addr,pfn) \
+ sparc32_cachetlb_ops->cache_page(vma, addr)
+#define flush_icache_range(start, end) do { } while (0)
+#define flush_icache_page(vma, pg) do { } while (0)
+
+#define flush_icache_user_range(vma,pg,adr,len) do { } while (0)
+
+#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
+ do { \
+ flush_cache_page(vma, vaddr, page_to_pfn(page));\
+ memcpy(dst, src, len); \
+ } while (0)
+#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
+ do { \
+ flush_cache_page(vma, vaddr, page_to_pfn(page));\
+ memcpy(dst, src, len); \
+ } while (0)
+
+#define __flush_page_to_ram(addr) \
+ sparc32_cachetlb_ops->page_to_ram(addr)
+#define flush_sig_insns(mm,insn_addr) \
+ sparc32_cachetlb_ops->sig_insns(mm, insn_addr)
+#define flush_page_for_dma(addr) \
+ sparc32_cachetlb_ops->page_for_dma(addr)
+
+void sparc_flush_page_to_ram(struct page *page);
+
+#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
+#define flush_dcache_page(page) sparc_flush_page_to_ram(page)
+#define flush_dcache_mmap_lock(mapping) do { } while (0)
+#define flush_dcache_mmap_unlock(mapping) do { } while (0)
+
+#define flush_cache_vmap(start, end) flush_cache_all()
+#define flush_cache_vunmap(start, end) flush_cache_all()
+
+/* When a context switch happens we must flush all user windows so that
+ * the windows of the current process are flushed onto its stack. This
+ * way the windows are all clean for the next process and the stack
+ * frames are up to date.
+ */
+void flush_user_windows(void);
+void kill_user_windows(void);
+void flushw_all(void);
+
+#endif /* _SPARC_CACHEFLUSH_H */
diff --git a/arch/sparc/include/asm/cacheflush_64.h b/arch/sparc/include/asm/cacheflush_64.h
new file mode 100644
index 00000000000..38965379e35
--- /dev/null
+++ b/arch/sparc/include/asm/cacheflush_64.h
@@ -0,0 +1,84 @@
+#ifndef _SPARC64_CACHEFLUSH_H
+#define _SPARC64_CACHEFLUSH_H
+
+#include <asm/page.h>
+
+#ifndef __ASSEMBLY__
+
+#include <linux/mm.h>
+
+/* Cache flush operations. */
+#define flushw_all() __asm__ __volatile__("flushw")
+
+void __flushw_user(void);
+#define flushw_user() __flushw_user()
+
+#define flush_user_windows flushw_user
+#define flush_register_windows flushw_all
+
+/* These are the same regardless of whether this is an SMP kernel or not. */
+#define flush_cache_mm(__mm) \
+ do { if ((__mm) == current->mm) flushw_user(); } while(0)
+#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
+#define flush_cache_range(vma, start, end) \
+ flush_cache_mm((vma)->vm_mm)
+#define flush_cache_page(vma, page, pfn) \
+ flush_cache_mm((vma)->vm_mm)
+
+/*
+ * On spitfire, the icache doesn't snoop local stores and we don't
+ * use block commit stores (which invalidate icache lines) during
+ * module load, so we need this.
+ */
+void flush_icache_range(unsigned long start, unsigned long end);
+void __flush_icache_page(unsigned long);
+
+void __flush_dcache_page(void *addr, int flush_icache);
+void flush_dcache_page_impl(struct page *page);
+#ifdef CONFIG_SMP
+void smp_flush_dcache_page_impl(struct page *page, int cpu);
+void flush_dcache_page_all(struct mm_struct *mm, struct page *page);
+#else
+#define smp_flush_dcache_page_impl(page,cpu) flush_dcache_page_impl(page)
+#define flush_dcache_page_all(mm,page) flush_dcache_page_impl(page)
+#endif
+
+void __flush_dcache_range(unsigned long start, unsigned long end);
+#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
+void flush_dcache_page(struct page *page);
+
+#define flush_icache_page(vma, pg) do { } while(0)
+#define flush_icache_user_range(vma,pg,adr,len) do { } while (0)
+
+void flush_ptrace_access(struct vm_area_struct *, struct page *,
+ unsigned long uaddr, void *kaddr,
+ unsigned long len, int write);
+
+#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
+ do { \
+ flush_cache_page(vma, vaddr, page_to_pfn(page)); \
+ memcpy(dst, src, len); \
+ flush_ptrace_access(vma, page, vaddr, src, len, 0); \
+ } while (0)
+
+#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
+ do { \
+ flush_cache_page(vma, vaddr, page_to_pfn(page)); \
+ memcpy(dst, src, len); \
+ flush_ptrace_access(vma, page, vaddr, dst, len, 1); \
+ } while (0)
+
+#define flush_dcache_mmap_lock(mapping) do { } while (0)
+#define flush_dcache_mmap_unlock(mapping) do { } while (0)
+
+#define flush_cache_vmap(start, end) do { } while (0)
+#define flush_cache_vunmap(start, end) do { } while (0)
+
+#ifdef CONFIG_DEBUG_PAGEALLOC
+/* internal debugging function */
+void kernel_map_pages(struct page *page, int numpages, int enable);
+#endif
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _SPARC64_CACHEFLUSH_H */
diff --git a/arch/sparc/include/asm/cachetlb_32.h b/arch/sparc/include/asm/cachetlb_32.h
new file mode 100644
index 00000000000..efb19889a08
--- /dev/null
+++ b/arch/sparc/include/asm/cachetlb_32.h
@@ -0,0 +1,29 @@
+#ifndef _SPARC_CACHETLB_H
+#define _SPARC_CACHETLB_H
+
+struct mm_struct;
+struct vm_area_struct;
+
+struct sparc32_cachetlb_ops {
+ void (*cache_all)(void);
+ void (*cache_mm)(struct mm_struct *);
+ void (*cache_range)(struct vm_area_struct *, unsigned long,
+ unsigned long);
+ void (*cache_page)(struct vm_area_struct *, unsigned long);
+
+ void (*tlb_all)(void);
+ void (*tlb_mm)(struct mm_struct *);
+ void (*tlb_range)(struct vm_area_struct *, unsigned long,
+ unsigned long);
+ void (*tlb_page)(struct vm_area_struct *, unsigned long);
+
+ void (*page_to_ram)(unsigned long);
+ void (*sig_insns)(struct mm_struct *, unsigned long);
+ void (*page_for_dma)(unsigned long);
+};
+extern const struct sparc32_cachetlb_ops *sparc32_cachetlb_ops;
+#ifdef CONFIG_SMP
+extern const struct sparc32_cachetlb_ops *local_ops;
+#endif
+
+#endif /* SPARC_CACHETLB_H */
diff --git a/arch/sparc/include/asm/chafsr.h b/arch/sparc/include/asm/chafsr.h
new file mode 100644
index 00000000000..85c69b38220
--- /dev/null
+++ b/arch/sparc/include/asm/chafsr.h
@@ -0,0 +1,241 @@
+#ifndef _SPARC64_CHAFSR_H
+#define _SPARC64_CHAFSR_H
+
+/* Cheetah Asynchronous Fault Status register, ASI=0x4C VA<63:0>=0x0 */
+
+/* Comments indicate which processor variants on which the bit definition
+ * is valid. Codes are:
+ * ch --> cheetah
+ * ch+ --> cheetah plus
+ * jp --> jalapeno
+ */
+
+/* All bits of this register except M_SYNDROME and E_SYNDROME are
+ * read, write 1 to clear. M_SYNDROME and E_SYNDROME are read-only.
+ */
+
+/* Software bit set by linux trap handlers to indicate that the trap was
+ * signalled at %tl >= 1.
+ */
+#define CHAFSR_TL1 (1UL << 63UL) /* n/a */
+
+/* Unmapped error from system bus for prefetch queue or
+ * store queue read operation
+ */
+#define CHPAFSR_DTO (1UL << 59UL) /* ch+ */
+
+/* Bus error from system bus for prefetch queue or store queue
+ * read operation
+ */
+#define CHPAFSR_DBERR (1UL << 58UL) /* ch+ */
+
+/* Hardware corrected E-cache Tag ECC error */
+#define CHPAFSR_THCE (1UL << 57UL) /* ch+ */
+/* System interface protocol error, hw timeout caused */
+#define JPAFSR_JETO (1UL << 57UL) /* jp */
+
+/* SW handled correctable E-cache Tag ECC error */
+#define CHPAFSR_TSCE (1UL << 56UL) /* ch+ */
+/* Parity error on system snoop results */
+#define JPAFSR_SCE (1UL << 56UL) /* jp */
+
+/* Uncorrectable E-cache Tag ECC error */
+#define CHPAFSR_TUE (1UL << 55UL) /* ch+ */
+/* System interface protocol error, illegal command detected */
+#define JPAFSR_JEIC (1UL << 55UL) /* jp */
+
+/* Uncorrectable system bus data ECC error due to prefetch
+ * or store fill request
+ */
+#define CHPAFSR_DUE (1UL << 54UL) /* ch+ */
+/* System interface protocol error, illegal ADTYPE detected */
+#define JPAFSR_JEIT (1UL << 54UL) /* jp */
+
+/* Multiple errors of the same type have occurred. This bit is set when
+ * an uncorrectable error or a SW correctable error occurs and the status
+ * bit to report that error is already set. When multiple errors of
+ * different types are indicated by setting multiple status bits.
+ *
+ * This bit is not set if multiple HW corrected errors with the same
+ * status bit occur, only uncorrectable and SW correctable ones have
+ * this behavior.
+ *
+ * This bit is not set when multiple ECC errors happen within a single
+ * 64-byte system bus transaction. Only the first ECC error in a 16-byte
+ * subunit will be logged. All errors in subsequent 16-byte subunits
+ * from the same 64-byte transaction are ignored.
+ */
+#define CHAFSR_ME (1UL << 53UL) /* ch,ch+,jp */
+
+/* Privileged state error has occurred. This is a capture of PSTATE.PRIV
+ * at the time the error is detected.
+ */
+#define CHAFSR_PRIV (1UL << 52UL) /* ch,ch+,jp */
+
+/* The following bits 51 (CHAFSR_PERR) to 33 (CHAFSR_CE) are sticky error
+ * bits and record the most recently detected errors. Bits accumulate
+ * errors that have been detected since the last write to clear the bit.
+ */
+
+/* System interface protocol error. The processor asserts its' ERROR
+ * pin when this event occurs and it also logs a specific cause code
+ * into a JTAG scannable flop.
+ */
+#define CHAFSR_PERR (1UL << 51UL) /* ch,ch+,jp */
+
+/* Internal processor error. The processor asserts its' ERROR
+ * pin when this event occurs and it also logs a specific cause code
+ * into a JTAG scannable flop.
+ */
+#define CHAFSR_IERR (1UL << 50UL) /* ch,ch+,jp */
+
+/* System request parity error on incoming address */
+#define CHAFSR_ISAP (1UL << 49UL) /* ch,ch+,jp */
+
+/* HW Corrected system bus MTAG ECC error */
+#define CHAFSR_EMC (1UL << 48UL) /* ch,ch+ */
+/* Parity error on L2 cache tag SRAM */
+#define JPAFSR_ETP (1UL << 48UL) /* jp */
+
+/* Uncorrectable system bus MTAG ECC error */
+#define CHAFSR_EMU (1UL << 47UL) /* ch,ch+ */
+/* Out of range memory error has occurred */
+#define JPAFSR_OM (1UL << 47UL) /* jp */
+
+/* HW Corrected system bus data ECC error for read of interrupt vector */
+#define CHAFSR_IVC (1UL << 46UL) /* ch,ch+ */
+/* Error due to unsupported store */
+#define JPAFSR_UMS (1UL << 46UL) /* jp */
+
+/* Uncorrectable system bus data ECC error for read of interrupt vector */
+#define CHAFSR_IVU (1UL << 45UL) /* ch,ch+,jp */
+
+/* Unmapped error from system bus */
+#define CHAFSR_TO (1UL << 44UL) /* ch,ch+,jp */
+
+/* Bus error response from system bus */
+#define CHAFSR_BERR (1UL << 43UL) /* ch,ch+,jp */
+
+/* SW Correctable E-cache ECC error for instruction fetch or data access
+ * other than block load.
+ */
+#define CHAFSR_UCC (1UL << 42UL) /* ch,ch+,jp */
+
+/* Uncorrectable E-cache ECC error for instruction fetch or data access
+ * other than block load.
+ */
+#define CHAFSR_UCU (1UL << 41UL) /* ch,ch+,jp */
+
+/* Copyout HW Corrected ECC error */
+#define CHAFSR_CPC (1UL << 40UL) /* ch,ch+,jp */
+
+/* Copyout Uncorrectable ECC error */
+#define CHAFSR_CPU (1UL << 39UL) /* ch,ch+,jp */
+
+/* HW Corrected ECC error from E-cache for writeback */
+#define CHAFSR_WDC (1UL << 38UL) /* ch,ch+,jp */
+
+/* Uncorrectable ECC error from E-cache for writeback */
+#define CHAFSR_WDU (1UL << 37UL) /* ch,ch+,jp */
+
+/* HW Corrected ECC error from E-cache for store merge or block load */
+#define CHAFSR_EDC (1UL << 36UL) /* ch,ch+,jp */
+
+/* Uncorrectable ECC error from E-cache for store merge or block load */
+#define CHAFSR_EDU (1UL << 35UL) /* ch,ch+,jp */
+
+/* Uncorrectable system bus data ECC error for read of memory or I/O */
+#define CHAFSR_UE (1UL << 34UL) /* ch,ch+,jp */
+
+/* HW Corrected system bus data ECC error for read of memory or I/O */
+#define CHAFSR_CE (1UL << 33UL) /* ch,ch+,jp */
+
+/* Uncorrectable ECC error from remote cache/memory */
+#define JPAFSR_RUE (1UL << 32UL) /* jp */
+
+/* Correctable ECC error from remote cache/memory */
+#define JPAFSR_RCE (1UL << 31UL) /* jp */
+
+/* JBUS parity error on returned read data */
+#define JPAFSR_BP (1UL << 30UL) /* jp */
+
+/* JBUS parity error on data for writeback or block store */
+#define JPAFSR_WBP (1UL << 29UL) /* jp */
+
+/* Foreign read to DRAM incurring correctable ECC error */
+#define JPAFSR_FRC (1UL << 28UL) /* jp */
+
+/* Foreign read to DRAM incurring uncorrectable ECC error */
+#define JPAFSR_FRU (1UL << 27UL) /* jp */
+
+#define CHAFSR_ERRORS (CHAFSR_PERR | CHAFSR_IERR | CHAFSR_ISAP | CHAFSR_EMC | \
+ CHAFSR_EMU | CHAFSR_IVC | CHAFSR_IVU | CHAFSR_TO | \
+ CHAFSR_BERR | CHAFSR_UCC | CHAFSR_UCU | CHAFSR_CPC | \
+ CHAFSR_CPU | CHAFSR_WDC | CHAFSR_WDU | CHAFSR_EDC | \
+ CHAFSR_EDU | CHAFSR_UE | CHAFSR_CE)
+#define CHPAFSR_ERRORS (CHPAFSR_DTO | CHPAFSR_DBERR | CHPAFSR_THCE | \
+ CHPAFSR_TSCE | CHPAFSR_TUE | CHPAFSR_DUE | \
+ CHAFSR_PERR | CHAFSR_IERR | CHAFSR_ISAP | CHAFSR_EMC | \
+ CHAFSR_EMU | CHAFSR_IVC | CHAFSR_IVU | CHAFSR_TO | \
+ CHAFSR_BERR | CHAFSR_UCC | CHAFSR_UCU | CHAFSR_CPC | \
+ CHAFSR_CPU | CHAFSR_WDC | CHAFSR_WDU | CHAFSR_EDC | \
+ CHAFSR_EDU | CHAFSR_UE | CHAFSR_CE)
+#define JPAFSR_ERRORS (JPAFSR_JETO | JPAFSR_SCE | JPAFSR_JEIC | \
+ JPAFSR_JEIT | CHAFSR_PERR | CHAFSR_IERR | \
+ CHAFSR_ISAP | JPAFSR_ETP | JPAFSR_OM | \
+ JPAFSR_UMS | CHAFSR_IVU | CHAFSR_TO | \
+ CHAFSR_BERR | CHAFSR_UCC | CHAFSR_UCU | \
+ CHAFSR_CPC | CHAFSR_CPU | CHAFSR_WDC | \
+ CHAFSR_WDU | CHAFSR_EDC | CHAFSR_EDU | \
+ CHAFSR_UE | CHAFSR_CE | JPAFSR_RUE | \
+ JPAFSR_RCE | JPAFSR_BP | JPAFSR_WBP | \
+ JPAFSR_FRC | JPAFSR_FRU)
+
+/* Active JBUS request signal when error occurred */
+#define JPAFSR_JBREQ (0x7UL << 24UL) /* jp */
+#define JPAFSR_JBREQ_SHIFT 24UL
+
+/* L2 cache way information */
+#define JPAFSR_ETW (0x3UL << 22UL) /* jp */
+#define JPAFSR_ETW_SHIFT 22UL
+
+/* System bus MTAG ECC syndrome. This field captures the status of the
+ * first occurrence of the highest-priority error according to the M_SYND
+ * overwrite policy. After the AFSR sticky bit, corresponding to the error
+ * for which the M_SYND is reported, is cleared, the contents of the M_SYND
+ * field will be unchanged by will be unfrozen for further error capture.
+ */
+#define CHAFSR_M_SYNDROME (0xfUL << 16UL) /* ch,ch+,jp */
+#define CHAFSR_M_SYNDROME_SHIFT 16UL
+
+/* Agenid Id of the foreign device causing the UE/CE errors */
+#define JPAFSR_AID (0x1fUL << 9UL) /* jp */
+#define JPAFSR_AID_SHIFT 9UL
+
+/* System bus or E-cache data ECC syndrome. This field captures the status
+ * of the first occurrence of the highest-priority error according to the
+ * E_SYND overwrite policy. After the AFSR sticky bit, corresponding to the
+ * error for which the E_SYND is reported, is cleare, the contents of the E_SYND
+ * field will be unchanged but will be unfrozen for further error capture.
+ */
+#define CHAFSR_E_SYNDROME (0x1ffUL << 0UL) /* ch,ch+,jp */
+#define CHAFSR_E_SYNDROME_SHIFT 0UL
+
+/* The AFSR must be explicitly cleared by software, it is not cleared automatically
+ * by a read. Writes to bits <51:33> with bits set will clear the corresponding
+ * bits in the AFSR. Bits associated with disrupting traps must be cleared before
+ * interrupts are re-enabled to prevent multiple traps for the same error. I.e.
+ * PSTATE.IE and AFSR bits control delivery of disrupting traps.
+ *
+ * Since there is only one AFAR, when multiple events have been logged by the
+ * bits in the AFSR, at most one of these events will have its status captured
+ * in the AFAR. The highest priority of those event bits will get AFAR logging.
+ * The AFAR will be unlocked and available to capture the address of another event
+ * as soon as the one bit in AFSR that corresponds to the event logged in AFAR is
+ * cleared. For example, if AFSR.CE is detected, then AFSR.UE (which overwrites
+ * the AFAR), and AFSR.UE is cleared by not AFSR.CE, then the AFAR will be unlocked
+ * and ready for another event, even though AFSR.CE is still set. The same rules
+ * also apply to the M_SYNDROME and E_SYNDROME fields of the AFSR.
+ */
+
+#endif /* _SPARC64_CHAFSR_H */
diff --git a/arch/sparc/include/asm/checksum.h b/arch/sparc/include/asm/checksum.h
new file mode 100644
index 00000000000..7ac0d7497bc
--- /dev/null
+++ b/arch/sparc/include/asm/checksum.h
@@ -0,0 +1,8 @@
+#ifndef ___ASM_SPARC_CHECKSUM_H
+#define ___ASM_SPARC_CHECKSUM_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/checksum_64.h>
+#else
+#include <asm/checksum_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/checksum_32.h b/arch/sparc/include/asm/checksum_32.h
new file mode 100644
index 00000000000..426b2389a1c
--- /dev/null
+++ b/arch/sparc/include/asm/checksum_32.h
@@ -0,0 +1,253 @@
+#ifndef __SPARC_CHECKSUM_H
+#define __SPARC_CHECKSUM_H
+
+/* checksum.h: IP/UDP/TCP checksum routines on the Sparc.
+ *
+ * Copyright(C) 1995 Linus Torvalds
+ * Copyright(C) 1995 Miguel de Icaza
+ * Copyright(C) 1996 David S. Miller
+ * Copyright(C) 1996 Eddie C. Dost
+ * Copyright(C) 1997 Jakub Jelinek
+ *
+ * derived from:
+ * Alpha checksum c-code
+ * ix86 inline assembly
+ * RFC1071 Computing the Internet Checksum
+ */
+
+#include <linux/in6.h>
+#include <asm/uaccess.h>
+
+/* computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+__wsum csum_partial(const void *buff, int len, __wsum sum);
+
+/* the same as csum_partial, but copies from fs:src while it
+ * checksums
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+
+unsigned int __csum_partial_copy_sparc_generic (const unsigned char *, unsigned char *);
+
+static inline __wsum
+csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum)
+{
+ register unsigned int ret asm("o0") = (unsigned int)src;
+ register char *d asm("o1") = dst;
+ register int l asm("g1") = len;
+
+ __asm__ __volatile__ (
+ "call __csum_partial_copy_sparc_generic\n\t"
+ " mov %6, %%g7\n"
+ : "=&r" (ret), "=&r" (d), "=&r" (l)
+ : "0" (ret), "1" (d), "2" (l), "r" (sum)
+ : "o2", "o3", "o4", "o5", "o7",
+ "g2", "g3", "g4", "g5", "g7",
+ "memory", "cc");
+ return (__force __wsum)ret;
+}
+
+static inline __wsum
+csum_partial_copy_from_user(const void __user *src, void *dst, int len,
+ __wsum sum, int *err)
+ {
+ register unsigned long ret asm("o0") = (unsigned long)src;
+ register char *d asm("o1") = dst;
+ register int l asm("g1") = len;
+ register __wsum s asm("g7") = sum;
+
+ __asm__ __volatile__ (
+ ".section __ex_table,#alloc\n\t"
+ ".align 4\n\t"
+ ".word 1f,2\n\t"
+ ".previous\n"
+ "1:\n\t"
+ "call __csum_partial_copy_sparc_generic\n\t"
+ " st %8, [%%sp + 64]\n"
+ : "=&r" (ret), "=&r" (d), "=&r" (l), "=&r" (s)
+ : "0" (ret), "1" (d), "2" (l), "3" (s), "r" (err)
+ : "o2", "o3", "o4", "o5", "o7", "g2", "g3", "g4", "g5",
+ "cc", "memory");
+ return (__force __wsum)ret;
+}
+
+static inline __wsum
+csum_partial_copy_to_user(const void *src, void __user *dst, int len,
+ __wsum sum, int *err)
+{
+ if (!access_ok (VERIFY_WRITE, dst, len)) {
+ *err = -EFAULT;
+ return sum;
+ } else {
+ register unsigned long ret asm("o0") = (unsigned long)src;
+ register char __user *d asm("o1") = dst;
+ register int l asm("g1") = len;
+ register __wsum s asm("g7") = sum;
+
+ __asm__ __volatile__ (
+ ".section __ex_table,#alloc\n\t"
+ ".align 4\n\t"
+ ".word 1f,1\n\t"
+ ".previous\n"
+ "1:\n\t"
+ "call __csum_partial_copy_sparc_generic\n\t"
+ " st %8, [%%sp + 64]\n"
+ : "=&r" (ret), "=&r" (d), "=&r" (l), "=&r" (s)
+ : "0" (ret), "1" (d), "2" (l), "3" (s), "r" (err)
+ : "o2", "o3", "o4", "o5", "o7",
+ "g2", "g3", "g4", "g5",
+ "cc", "memory");
+ return (__force __wsum)ret;
+ }
+}
+
+#define HAVE_CSUM_COPY_USER
+#define csum_and_copy_to_user csum_partial_copy_to_user
+
+/* ihl is always 5 or greater, almost always is 5, and iph is word aligned
+ * the majority of the time.
+ */
+static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
+{
+ __sum16 sum;
+
+ /* Note: We must read %2 before we touch %0 for the first time,
+ * because GCC can legitimately use the same register for
+ * both operands.
+ */
+ __asm__ __volatile__("sub\t%2, 4, %%g4\n\t"
+ "ld\t[%1 + 0x00], %0\n\t"
+ "ld\t[%1 + 0x04], %%g2\n\t"
+ "ld\t[%1 + 0x08], %%g3\n\t"
+ "addcc\t%%g2, %0, %0\n\t"
+ "addxcc\t%%g3, %0, %0\n\t"
+ "ld\t[%1 + 0x0c], %%g2\n\t"
+ "ld\t[%1 + 0x10], %%g3\n\t"
+ "addxcc\t%%g2, %0, %0\n\t"
+ "addx\t%0, %%g0, %0\n"
+ "1:\taddcc\t%%g3, %0, %0\n\t"
+ "add\t%1, 4, %1\n\t"
+ "addxcc\t%0, %%g0, %0\n\t"
+ "subcc\t%%g4, 1, %%g4\n\t"
+ "be,a\t2f\n\t"
+ "sll\t%0, 16, %%g2\n\t"
+ "b\t1b\n\t"
+ "ld\t[%1 + 0x10], %%g3\n"
+ "2:\taddcc\t%0, %%g2, %%g2\n\t"
+ "srl\t%%g2, 16, %0\n\t"
+ "addx\t%0, %%g0, %0\n\t"
+ "xnor\t%%g0, %0, %0"
+ : "=r" (sum), "=&r" (iph)
+ : "r" (ihl), "1" (iph)
+ : "g2", "g3", "g4", "cc", "memory");
+ return sum;
+}
+
+/* Fold a partial checksum without adding pseudo headers. */
+static inline __sum16 csum_fold(__wsum sum)
+{
+ unsigned int tmp;
+
+ __asm__ __volatile__("addcc\t%0, %1, %1\n\t"
+ "srl\t%1, 16, %1\n\t"
+ "addx\t%1, %%g0, %1\n\t"
+ "xnor\t%%g0, %1, %0"
+ : "=&r" (sum), "=r" (tmp)
+ : "0" (sum), "1" ((__force u32)sum<<16)
+ : "cc");
+ return (__force __sum16)sum;
+}
+
+static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
+ unsigned short len,
+ unsigned short proto,
+ __wsum sum)
+{
+ __asm__ __volatile__("addcc\t%1, %0, %0\n\t"
+ "addxcc\t%2, %0, %0\n\t"
+ "addxcc\t%3, %0, %0\n\t"
+ "addx\t%0, %%g0, %0\n\t"
+ : "=r" (sum), "=r" (saddr)
+ : "r" (daddr), "r" (proto + len), "0" (sum),
+ "1" (saddr)
+ : "cc");
+ return sum;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
+ unsigned short len,
+ unsigned short proto,
+ __wsum sum)
+{
+ return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
+}
+
+#define _HAVE_ARCH_IPV6_CSUM
+
+static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+ const struct in6_addr *daddr,
+ __u32 len, unsigned short proto,
+ __wsum sum)
+{
+ __asm__ __volatile__ (
+ "addcc %3, %4, %%g4\n\t"
+ "addxcc %5, %%g4, %%g4\n\t"
+ "ld [%2 + 0x0c], %%g2\n\t"
+ "ld [%2 + 0x08], %%g3\n\t"
+ "addxcc %%g2, %%g4, %%g4\n\t"
+ "ld [%2 + 0x04], %%g2\n\t"
+ "addxcc %%g3, %%g4, %%g4\n\t"
+ "ld [%2 + 0x00], %%g3\n\t"
+ "addxcc %%g2, %%g4, %%g4\n\t"
+ "ld [%1 + 0x0c], %%g2\n\t"
+ "addxcc %%g3, %%g4, %%g4\n\t"
+ "ld [%1 + 0x08], %%g3\n\t"
+ "addxcc %%g2, %%g4, %%g4\n\t"
+ "ld [%1 + 0x04], %%g2\n\t"
+ "addxcc %%g3, %%g4, %%g4\n\t"
+ "ld [%1 + 0x00], %%g3\n\t"
+ "addxcc %%g2, %%g4, %%g4\n\t"
+ "addxcc %%g3, %%g4, %0\n\t"
+ "addx 0, %0, %0\n"
+ : "=&r" (sum)
+ : "r" (saddr), "r" (daddr),
+ "r"(htonl(len)), "r"(htonl(proto)), "r"(sum)
+ : "g2", "g3", "g4", "cc");
+
+ return csum_fold(sum);
+}
+
+/* this routine is used for miscellaneous IP-like checksums, mainly in icmp.c */
+static inline __sum16 ip_compute_csum(const void *buff, int len)
+{
+ return csum_fold(csum_partial(buff, len, 0));
+}
+
+#define HAVE_ARCH_CSUM_ADD
+static inline __wsum csum_add(__wsum csum, __wsum addend)
+{
+ __asm__ __volatile__(
+ "addcc %0, %1, %0\n"
+ "addx %0, %%g0, %0"
+ : "=r" (csum)
+ : "r" (addend), "0" (csum));
+
+ return csum;
+}
+
+#endif /* !(__SPARC_CHECKSUM_H) */
diff --git a/arch/sparc/include/asm/checksum_64.h b/arch/sparc/include/asm/checksum_64.h
new file mode 100644
index 00000000000..b8779a6a591
--- /dev/null
+++ b/arch/sparc/include/asm/checksum_64.h
@@ -0,0 +1,179 @@
+#ifndef __SPARC64_CHECKSUM_H
+#define __SPARC64_CHECKSUM_H
+
+/* checksum.h: IP/UDP/TCP checksum routines on the V9.
+ *
+ * Copyright(C) 1995 Linus Torvalds
+ * Copyright(C) 1995 Miguel de Icaza
+ * Copyright(C) 1996 David S. Miller
+ * Copyright(C) 1996 Eddie C. Dost
+ * Copyright(C) 1997 Jakub Jelinek
+ *
+ * derived from:
+ * Alpha checksum c-code
+ * ix86 inline assembly
+ * RFC1071 Computing the Internet Checksum
+ */
+
+#include <linux/in6.h>
+#include <asm/uaccess.h>
+
+/* computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+__wsum csum_partial(const void * buff, int len, __wsum sum);
+
+/* the same as csum_partial, but copies from user space while it
+ * checksums
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+__wsum csum_partial_copy_nocheck(const void *src, void *dst,
+ int len, __wsum sum);
+
+long __csum_partial_copy_from_user(const void __user *src,
+ void *dst, int len,
+ __wsum sum);
+
+static inline __wsum
+csum_partial_copy_from_user(const void __user *src,
+ void *dst, int len,
+ __wsum sum, int *err)
+{
+ long ret = __csum_partial_copy_from_user(src, dst, len, sum);
+ if (ret < 0)
+ *err = -EFAULT;
+ return (__force __wsum) ret;
+}
+
+/*
+ * Copy and checksum to user
+ */
+#define HAVE_CSUM_COPY_USER
+long __csum_partial_copy_to_user(const void *src,
+ void __user *dst, int len,
+ __wsum sum);
+
+static inline __wsum
+csum_and_copy_to_user(const void *src,
+ void __user *dst, int len,
+ __wsum sum, int *err)
+{
+ long ret = __csum_partial_copy_to_user(src, dst, len, sum);
+ if (ret < 0)
+ *err = -EFAULT;
+ return (__force __wsum) ret;
+}
+
+/* ihl is always 5 or greater, almost always is 5, and iph is word aligned
+ * the majority of the time.
+ */
+__sum16 ip_fast_csum(const void *iph, unsigned int ihl);
+
+/* Fold a partial checksum without adding pseudo headers. */
+static inline __sum16 csum_fold(__wsum sum)
+{
+ unsigned int tmp;
+
+ __asm__ __volatile__(
+" addcc %0, %1, %1\n"
+" srl %1, 16, %1\n"
+" addc %1, %%g0, %1\n"
+" xnor %%g0, %1, %0\n"
+ : "=&r" (sum), "=r" (tmp)
+ : "0" (sum), "1" ((__force u32)sum<<16)
+ : "cc");
+ return (__force __sum16)sum;
+}
+
+static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
+ unsigned int len,
+ unsigned short proto,
+ __wsum sum)
+{
+ __asm__ __volatile__(
+" addcc %1, %0, %0\n"
+" addccc %2, %0, %0\n"
+" addccc %3, %0, %0\n"
+" addc %0, %%g0, %0\n"
+ : "=r" (sum), "=r" (saddr)
+ : "r" (daddr), "r" (proto + len), "0" (sum), "1" (saddr)
+ : "cc");
+ return sum;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
+ unsigned short len,
+ unsigned short proto,
+ __wsum sum)
+{
+ return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
+}
+
+#define _HAVE_ARCH_IPV6_CSUM
+
+static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+ const struct in6_addr *daddr,
+ __u32 len, unsigned short proto,
+ __wsum sum)
+{
+ __asm__ __volatile__ (
+" addcc %3, %4, %%g7\n"
+" addccc %5, %%g7, %%g7\n"
+" lduw [%2 + 0x0c], %%g2\n"
+" lduw [%2 + 0x08], %%g3\n"
+" addccc %%g2, %%g7, %%g7\n"
+" lduw [%2 + 0x04], %%g2\n"
+" addccc %%g3, %%g7, %%g7\n"
+" lduw [%2 + 0x00], %%g3\n"
+" addccc %%g2, %%g7, %%g7\n"
+" lduw [%1 + 0x0c], %%g2\n"
+" addccc %%g3, %%g7, %%g7\n"
+" lduw [%1 + 0x08], %%g3\n"
+" addccc %%g2, %%g7, %%g7\n"
+" lduw [%1 + 0x04], %%g2\n"
+" addccc %%g3, %%g7, %%g7\n"
+" lduw [%1 + 0x00], %%g3\n"
+" addccc %%g2, %%g7, %%g7\n"
+" addccc %%g3, %%g7, %0\n"
+" addc 0, %0, %0\n"
+ : "=&r" (sum)
+ : "r" (saddr), "r" (daddr), "r"(htonl(len)),
+ "r"(htonl(proto)), "r"(sum)
+ : "g2", "g3", "g7", "cc");
+
+ return csum_fold(sum);
+}
+
+/* this routine is used for miscellaneous IP-like checksums, mainly in icmp.c */
+static inline __sum16 ip_compute_csum(const void *buff, int len)
+{
+ return csum_fold(csum_partial(buff, len, 0));
+}
+
+#define HAVE_ARCH_CSUM_ADD
+static inline __wsum csum_add(__wsum csum, __wsum addend)
+{
+ __asm__ __volatile__(
+ "addcc %0, %1, %0\n"
+ "addx %0, %%g0, %0"
+ : "=r" (csum)
+ : "r" (addend), "0" (csum));
+
+ return csum;
+}
+
+#endif /* !(__SPARC64_CHECKSUM_H) */
diff --git a/arch/sparc/include/asm/chmctrl.h b/arch/sparc/include/asm/chmctrl.h
new file mode 100644
index 00000000000..859b4a4b0d3
--- /dev/null
+++ b/arch/sparc/include/asm/chmctrl.h
@@ -0,0 +1,183 @@
+#ifndef _SPARC64_CHMCTRL_H
+#define _SPARC64_CHMCTRL_H
+
+/* Cheetah memory controller programmable registers. */
+#define CHMCTRL_TCTRL1 0x00 /* Memory Timing Control I */
+#define CHMCTRL_TCTRL2 0x08 /* Memory Timing Control II */
+#define CHMCTRL_TCTRL3 0x38 /* Memory Timing Control III */
+#define CHMCTRL_TCTRL4 0x40 /* Memory Timing Control IV */
+#define CHMCTRL_DECODE1 0x10 /* Memory Address Decode I */
+#define CHMCTRL_DECODE2 0x18 /* Memory Address Decode II */
+#define CHMCTRL_DECODE3 0x20 /* Memory Address Decode III */
+#define CHMCTRL_DECODE4 0x28 /* Memory Address Decode IV */
+#define CHMCTRL_MACTRL 0x30 /* Memory Address Control */
+
+/* Memory Timing Control I */
+#define TCTRL1_SDRAMCTL_DLY 0xf000000000000000UL
+#define TCTRL1_SDRAMCTL_DLY_SHIFT 60
+#define TCTRL1_SDRAMCLK_DLY 0x0e00000000000000UL
+#define TCTRL1_SDRAMCLK_DLY_SHIFT 57
+#define TCTRL1_R 0x0100000000000000UL
+#define TCTRL1_R_SHIFT 56
+#define TCTRL1_AUTORFR_CYCLE 0x00fe000000000000UL
+#define TCTRL1_AUTORFR_CYCLE_SHIFT 49
+#define TCTRL1_RD_WAIT 0x0001f00000000000UL
+#define TCTRL1_RD_WAIT_SHIFT 44
+#define TCTRL1_PC_CYCLE 0x00000fc000000000UL
+#define TCTRL1_PC_CYCLE_SHIFT 38
+#define TCTRL1_WR_MORE_RAS_PW 0x0000003f00000000UL
+#define TCTRL1_WR_MORE_RAS_PW_SHIFT 32
+#define TCTRL1_RD_MORE_RAW_PW 0x00000000fc000000UL
+#define TCTRL1_RD_MORE_RAS_PW_SHIFT 26
+#define TCTRL1_ACT_WR_DLY 0x0000000003f00000UL
+#define TCTRL1_ACT_WR_DLY_SHIFT 20
+#define TCTRL1_ACT_RD_DLY 0x00000000000fc000UL
+#define TCTRL1_ACT_RD_DLY_SHIFT 14
+#define TCTRL1_BANK_PRESENT 0x0000000000003000UL
+#define TCTRL1_BANK_PRESENT_SHIFT 12
+#define TCTRL1_RFR_INT 0x0000000000000ff8UL
+#define TCTRL1_RFR_INT_SHIFT 3
+#define TCTRL1_SET_MODE_REG 0x0000000000000004UL
+#define TCTRL1_SET_MODE_REG_SHIFT 2
+#define TCTRL1_RFR_ENABLE 0x0000000000000002UL
+#define TCTRL1_RFR_ENABLE_SHIFT 1
+#define TCTRL1_PRECHG_ALL 0x0000000000000001UL
+#define TCTRL1_PRECHG_ALL_SHIFT 0
+
+/* Memory Timing Control II */
+#define TCTRL2_WR_MSEL_DLY 0xfc00000000000000UL
+#define TCTRL2_WR_MSEL_DLY_SHIFT 58
+#define TCTRL2_RD_MSEL_DLY 0x03f0000000000000UL
+#define TCTRL2_RD_MSEL_DLY_SHIFT 52
+#define TCTRL2_WRDATA_THLD 0x000c000000000000UL
+#define TCTRL2_WRDATA_THLD_SHIFT 50
+#define TCTRL2_RDWR_RD_TI_DLY 0x0003f00000000000UL
+#define TCTRL2_RDWR_RD_TI_DLY_SHIFT 44
+#define TCTRL2_AUTOPRECHG_ENBL 0x0000080000000000UL
+#define TCTRL2_AUTOPRECHG_ENBL_SHIFT 43
+#define TCTRL2_RDWR_PI_MORE_DLY 0x000007c000000000UL
+#define TCTRL2_RDWR_PI_MORE_DLY_SHIFT 38
+#define TCTRL2_RDWR_1_DLY 0x0000003f00000000UL
+#define TCTRL2_RDWR_1_DLY_SHIFT 32
+#define TCTRL2_WRWR_PI_MORE_DLY 0x00000000f8000000UL
+#define TCTRL2_WRWR_PI_MORE_DLY_SHIFT 27
+#define TCTRL2_WRWR_1_DLY 0x0000000007e00000UL
+#define TCTRL2_WRWR_1_DLY_SHIFT 21
+#define TCTRL2_RDWR_RD_PI_MORE_DLY 0x00000000001f0000UL
+#define TCTRL2_RDWR_RD_PI_MORE_DLY_SHIFT 16
+#define TCTRL2_R 0x0000000000008000UL
+#define TCTRL2_R_SHIFT 15
+#define TCTRL2_SDRAM_MODE_REG_DATA 0x0000000000007fffUL
+#define TCTRL2_SDRAM_MODE_REG_DATA_SHIFT 0
+
+/* Memory Timing Control III */
+#define TCTRL3_SDRAM_CTL_DLY 0xf000000000000000UL
+#define TCTRL3_SDRAM_CTL_DLY_SHIFT 60
+#define TCTRL3_SDRAM_CLK_DLY 0x0e00000000000000UL
+#define TCTRL3_SDRAM_CLK_DLY_SHIFT 57
+#define TCTRL3_R 0x0100000000000000UL
+#define TCTRL3_R_SHIFT 56
+#define TCTRL3_AUTO_RFR_CYCLE 0x00fe000000000000UL
+#define TCTRL3_AUTO_RFR_CYCLE_SHIFT 49
+#define TCTRL3_RD_WAIT 0x0001f00000000000UL
+#define TCTRL3_RD_WAIT_SHIFT 44
+#define TCTRL3_PC_CYCLE 0x00000fc000000000UL
+#define TCTRL3_PC_CYCLE_SHIFT 38
+#define TCTRL3_WR_MORE_RAW_PW 0x0000003f00000000UL
+#define TCTRL3_WR_MORE_RAW_PW_SHIFT 32
+#define TCTRL3_RD_MORE_RAW_PW 0x00000000fc000000UL
+#define TCTRL3_RD_MORE_RAW_PW_SHIFT 26
+#define TCTRL3_ACT_WR_DLY 0x0000000003f00000UL
+#define TCTRL3_ACT_WR_DLY_SHIFT 20
+#define TCTRL3_ACT_RD_DLY 0x00000000000fc000UL
+#define TCTRL3_ACT_RD_DLY_SHIFT 14
+#define TCTRL3_BANK_PRESENT 0x0000000000003000UL
+#define TCTRL3_BANK_PRESENT_SHIFT 12
+#define TCTRL3_RFR_INT 0x0000000000000ff8UL
+#define TCTRL3_RFR_INT_SHIFT 3
+#define TCTRL3_SET_MODE_REG 0x0000000000000004UL
+#define TCTRL3_SET_MODE_REG_SHIFT 2
+#define TCTRL3_RFR_ENABLE 0x0000000000000002UL
+#define TCTRL3_RFR_ENABLE_SHIFT 1
+#define TCTRL3_PRECHG_ALL 0x0000000000000001UL
+#define TCTRL3_PRECHG_ALL_SHIFT 0
+
+/* Memory Timing Control IV */
+#define TCTRL4_WR_MSEL_DLY 0xfc00000000000000UL
+#define TCTRL4_WR_MSEL_DLY_SHIFT 58
+#define TCTRL4_RD_MSEL_DLY 0x03f0000000000000UL
+#define TCTRL4_RD_MSEL_DLY_SHIFT 52
+#define TCTRL4_WRDATA_THLD 0x000c000000000000UL
+#define TCTRL4_WRDATA_THLD_SHIFT 50
+#define TCTRL4_RDWR_RD_RI_DLY 0x0003f00000000000UL
+#define TCTRL4_RDWR_RD_RI_DLY_SHIFT 44
+#define TCTRL4_AUTO_PRECHG_ENBL 0x0000080000000000UL
+#define TCTRL4_AUTO_PRECHG_ENBL_SHIFT 43
+#define TCTRL4_RD_WR_PI_MORE_DLY 0x000007c000000000UL
+#define TCTRL4_RD_WR_PI_MORE_DLY_SHIFT 38
+#define TCTRL4_RD_WR_TI_DLY 0x0000003f00000000UL
+#define TCTRL4_RD_WR_TI_DLY_SHIFT 32
+#define TCTRL4_WR_WR_PI_MORE_DLY 0x00000000f8000000UL
+#define TCTRL4_WR_WR_PI_MORE_DLY_SHIFT 27
+#define TCTRL4_WR_WR_TI_DLY 0x0000000007e00000UL
+#define TCTRL4_WR_WR_TI_DLY_SHIFT 21
+#define TCTRL4_RDWR_RD_PI_MORE_DLY 0x00000000001f000UL0
+#define TCTRL4_RDWR_RD_PI_MORE_DLY_SHIFT 16
+#define TCTRL4_R 0x0000000000008000UL
+#define TCTRL4_R_SHIFT 15
+#define TCTRL4_SDRAM_MODE_REG_DATA 0x0000000000007fffUL
+#define TCTRL4_SDRAM_MODE_REG_DATA_SHIFT 0
+
+/* All 4 memory address decoding registers have the
+ * same layout.
+ */
+#define MEM_DECODE_VALID 0x8000000000000000UL /* Valid */
+#define MEM_DECODE_VALID_SHIFT 63
+#define MEM_DECODE_UK 0x001ffe0000000000UL /* Upper mask */
+#define MEM_DECODE_UK_SHIFT 41
+#define MEM_DECODE_UM 0x0000001ffff00000UL /* Upper match */
+#define MEM_DECODE_UM_SHIFT 20
+#define MEM_DECODE_LK 0x000000000003c000UL /* Lower mask */
+#define MEM_DECODE_LK_SHIFT 14
+#define MEM_DECODE_LM 0x0000000000000f00UL /* Lower match */
+#define MEM_DECODE_LM_SHIFT 8
+
+#define PA_UPPER_BITS 0x000007fffc000000UL
+#define PA_UPPER_BITS_SHIFT 26
+#define PA_LOWER_BITS 0x00000000000003c0UL
+#define PA_LOWER_BITS_SHIFT 6
+
+#define MACTRL_R0 0x8000000000000000UL
+#define MACTRL_R0_SHIFT 63
+#define MACTRL_ADDR_LE_PW 0x7000000000000000UL
+#define MACTRL_ADDR_LE_PW_SHIFT 60
+#define MACTRL_CMD_PW 0x0f00000000000000UL
+#define MACTRL_CMD_PW_SHIFT 56
+#define MACTRL_HALF_MODE_WR_MSEL_DLY 0x00fc000000000000UL
+#define MACTRL_HALF_MODE_WR_MSEL_DLY_SHIFT 50
+#define MACTRL_HALF_MODE_RD_MSEL_DLY 0x0003f00000000000UL
+#define MACTRL_HALF_MODE_RD_MSEL_DLY_SHIFT 44
+#define MACTRL_HALF_MODE_SDRAM_CTL_DLY 0x00000f0000000000UL
+#define MACTRL_HALF_MODE_SDRAM_CTL_DLY_SHIFT 40
+#define MACTRL_HALF_MODE_SDRAM_CLK_DLY 0x000000e000000000UL
+#define MACTRL_HALF_MODE_SDRAM_CLK_DLY_SHIFT 37
+#define MACTRL_R1 0x0000001000000000UL
+#define MACTRL_R1_SHIFT 36
+#define MACTRL_BANKSEL_N_ROWADDR_SIZE_B3 0x0000000f00000000UL
+#define MACTRL_BANKSEL_N_ROWADDR_SIZE_B3_SHIFT 32
+#define MACTRL_ENC_INTLV_B3 0x00000000f8000000UL
+#define MACTRL_ENC_INTLV_B3_SHIFT 27
+#define MACTRL_BANKSEL_N_ROWADDR_SIZE_B2 0x0000000007800000UL
+#define MACTRL_BANKSEL_N_ROWADDR_SIZE_B2_SHIFT 23
+#define MACTRL_ENC_INTLV_B2 0x00000000007c0000UL
+#define MACTRL_ENC_INTLV_B2_SHIFT 18
+#define MACTRL_BANKSEL_N_ROWADDR_SIZE_B1 0x000000000003c000UL
+#define MACTRL_BANKSEL_N_ROWADDR_SIZE_B1_SHIFT 14
+#define MACTRL_ENC_INTLV_B1 0x0000000000003e00UL
+#define MACTRL_ENC_INTLV_B1_SHIFT 9
+#define MACTRL_BANKSEL_N_ROWADDR_SIZE_B0 0x00000000000001e0UL
+#define MACTRL_BANKSEL_N_ROWADDR_SIZE_B0_SHIFT 5
+#define MACTRL_ENC_INTLV_B0 0x000000000000001fUL
+#define MACTRL_ENC_INTLV_B0_SHIFT 0
+
+#endif /* _SPARC64_CHMCTRL_H */
diff --git a/arch/sparc/include/asm/clock.h b/arch/sparc/include/asm/clock.h
new file mode 100644
index 00000000000..2cf99dadec5
--- /dev/null
+++ b/arch/sparc/include/asm/clock.h
@@ -0,0 +1,11 @@
+/*
+ * clock.h: Definitions for clock operations on the Sparc.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+#ifndef _SPARC_CLOCK_H
+#define _SPARC_CLOCK_H
+
+/* Foo for now. */
+
+#endif /* !(_SPARC_CLOCK_H) */
diff --git a/arch/sparc/include/asm/cmpxchg.h b/arch/sparc/include/asm/cmpxchg.h
new file mode 100644
index 00000000000..9355893efa5
--- /dev/null
+++ b/arch/sparc/include/asm/cmpxchg.h
@@ -0,0 +1,8 @@
+#ifndef ___ASM_SPARC_CMPXCHG_H
+#define ___ASM_SPARC_CMPXCHG_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/cmpxchg_64.h>
+#else
+#include <asm/cmpxchg_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/cmpxchg_32.h b/arch/sparc/include/asm/cmpxchg_32.h
new file mode 100644
index 00000000000..32c29a133f9
--- /dev/null
+++ b/arch/sparc/include/asm/cmpxchg_32.h
@@ -0,0 +1,85 @@
+/* 32-bit atomic xchg() and cmpxchg() definitions.
+ *
+ * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com.au)
+ * Copyright (C) 2007 Kyle McMartin (kyle@parisc-linux.org)
+ *
+ * Additions by Keith M Wesolowski (wesolows@foobazco.org) based
+ * on asm-parisc/atomic.h Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>.
+ */
+
+#ifndef __ARCH_SPARC_CMPXCHG__
+#define __ARCH_SPARC_CMPXCHG__
+
+static inline unsigned long xchg_u32(__volatile__ unsigned long *m, unsigned long val)
+{
+ __asm__ __volatile__("swap [%2], %0"
+ : "=&r" (val)
+ : "0" (val), "r" (m)
+ : "memory");
+ return val;
+}
+
+void __xchg_called_with_bad_pointer(void);
+
+static inline unsigned long __xchg(unsigned long x, __volatile__ void * ptr, int size)
+{
+ switch (size) {
+ case 4:
+ return xchg_u32(ptr, x);
+ }
+ __xchg_called_with_bad_pointer();
+ return x;
+}
+
+#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+
+/* Emulate cmpxchg() the same way we emulate atomics,
+ * by hashing the object address and indexing into an array
+ * of spinlocks to get a bit of performance...
+ *
+ * See arch/sparc/lib/atomic32.c for implementation.
+ *
+ * Cribbed from <asm-parisc/atomic.h>
+ */
+#define __HAVE_ARCH_CMPXCHG 1
+
+/* bug catcher for when unsupported size is used - won't link */
+void __cmpxchg_called_with_bad_pointer(void);
+/* we only need to support cmpxchg of a u32 on sparc */
+unsigned long __cmpxchg_u32(volatile u32 *m, u32 old, u32 new_);
+
+/* don't worry...optimizer will get rid of most of this */
+static inline unsigned long
+__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new_, int size)
+{
+ switch (size) {
+ case 4:
+ return __cmpxchg_u32((u32 *)ptr, (u32)old, (u32)new_);
+ default:
+ __cmpxchg_called_with_bad_pointer();
+ break;
+ }
+ return old;
+}
+
+#define cmpxchg(ptr, o, n) \
+({ \
+ __typeof__(*(ptr)) _o_ = (o); \
+ __typeof__(*(ptr)) _n_ = (n); \
+ (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \
+ (unsigned long)_n_, sizeof(*(ptr))); \
+})
+
+#include <asm-generic/cmpxchg-local.h>
+
+/*
+ * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
+ * them available.
+ */
+#define cmpxchg_local(ptr, o, n) \
+ ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
+ (unsigned long)(n), sizeof(*(ptr))))
+#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
+
+#endif /* __ARCH_SPARC_CMPXCHG__ */
diff --git a/arch/sparc/include/asm/cmpxchg_64.h b/arch/sparc/include/asm/cmpxchg_64.h
new file mode 100644
index 00000000000..0e1ed6cfbf6
--- /dev/null
+++ b/arch/sparc/include/asm/cmpxchg_64.h
@@ -0,0 +1,146 @@
+/* 64-bit atomic xchg() and cmpxchg() definitions.
+ *
+ * Copyright (C) 1996, 1997, 2000 David S. Miller (davem@redhat.com)
+ */
+
+#ifndef __ARCH_SPARC64_CMPXCHG__
+#define __ARCH_SPARC64_CMPXCHG__
+
+static inline unsigned long xchg32(__volatile__ unsigned int *m, unsigned int val)
+{
+ unsigned long tmp1, tmp2;
+
+ __asm__ __volatile__(
+" mov %0, %1\n"
+"1: lduw [%4], %2\n"
+" cas [%4], %2, %0\n"
+" cmp %2, %0\n"
+" bne,a,pn %%icc, 1b\n"
+" mov %1, %0\n"
+ : "=&r" (val), "=&r" (tmp1), "=&r" (tmp2)
+ : "0" (val), "r" (m)
+ : "cc", "memory");
+ return val;
+}
+
+static inline unsigned long xchg64(__volatile__ unsigned long *m, unsigned long val)
+{
+ unsigned long tmp1, tmp2;
+
+ __asm__ __volatile__(
+" mov %0, %1\n"
+"1: ldx [%4], %2\n"
+" casx [%4], %2, %0\n"
+" cmp %2, %0\n"
+" bne,a,pn %%xcc, 1b\n"
+" mov %1, %0\n"
+ : "=&r" (val), "=&r" (tmp1), "=&r" (tmp2)
+ : "0" (val), "r" (m)
+ : "cc", "memory");
+ return val;
+}
+
+#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+
+void __xchg_called_with_bad_pointer(void);
+
+static inline unsigned long __xchg(unsigned long x, __volatile__ void * ptr,
+ int size)
+{
+ switch (size) {
+ case 4:
+ return xchg32(ptr, x);
+ case 8:
+ return xchg64(ptr, x);
+ }
+ __xchg_called_with_bad_pointer();
+ return x;
+}
+
+/*
+ * Atomic compare and exchange. Compare OLD with MEM, if identical,
+ * store NEW in MEM. Return the initial value in MEM. Success is
+ * indicated by comparing RETURN with OLD.
+ */
+
+#include <asm-generic/cmpxchg-local.h>
+
+#define __HAVE_ARCH_CMPXCHG 1
+
+static inline unsigned long
+__cmpxchg_u32(volatile int *m, int old, int new)
+{
+ __asm__ __volatile__("cas [%2], %3, %0"
+ : "=&r" (new)
+ : "0" (new), "r" (m), "r" (old)
+ : "memory");
+
+ return new;
+}
+
+static inline unsigned long
+__cmpxchg_u64(volatile long *m, unsigned long old, unsigned long new)
+{
+ __asm__ __volatile__("casx [%2], %3, %0"
+ : "=&r" (new)
+ : "0" (new), "r" (m), "r" (old)
+ : "memory");
+
+ return new;
+}
+
+/* This function doesn't exist, so you'll get a linker error
+ if something tries to do an invalid cmpxchg(). */
+void __cmpxchg_called_with_bad_pointer(void);
+
+static inline unsigned long
+__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
+{
+ switch (size) {
+ case 4:
+ return __cmpxchg_u32(ptr, old, new);
+ case 8:
+ return __cmpxchg_u64(ptr, old, new);
+ }
+ __cmpxchg_called_with_bad_pointer();
+ return old;
+}
+
+#define cmpxchg(ptr,o,n) \
+ ({ \
+ __typeof__(*(ptr)) _o_ = (o); \
+ __typeof__(*(ptr)) _n_ = (n); \
+ (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \
+ (unsigned long)_n_, sizeof(*(ptr))); \
+ })
+
+/*
+ * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
+ * them available.
+ */
+
+static inline unsigned long __cmpxchg_local(volatile void *ptr,
+ unsigned long old,
+ unsigned long new, int size)
+{
+ switch (size) {
+ case 4:
+ case 8: return __cmpxchg(ptr, old, new, size);
+ default:
+ return __cmpxchg_local_generic(ptr, old, new, size);
+ }
+
+ return old;
+}
+
+#define cmpxchg_local(ptr, o, n) \
+ ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o), \
+ (unsigned long)(n), sizeof(*(ptr))))
+#define cmpxchg64_local(ptr, o, n) \
+ ({ \
+ BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
+ cmpxchg_local((ptr), (o), (n)); \
+ })
+#define cmpxchg64(ptr, o, n) cmpxchg64_local((ptr), (o), (n))
+
+#endif /* __ARCH_SPARC64_CMPXCHG__ */
diff --git a/arch/sparc/include/asm/compat.h b/arch/sparc/include/asm/compat.h
new file mode 100644
index 00000000000..830502fe62b
--- /dev/null
+++ b/arch/sparc/include/asm/compat.h
@@ -0,0 +1,310 @@
+#ifndef _ASM_SPARC64_COMPAT_H
+#define _ASM_SPARC64_COMPAT_H
+/*
+ * Architecture specific compatibility types
+ */
+#include <linux/types.h>
+
+#define COMPAT_USER_HZ 100
+#define COMPAT_UTS_MACHINE "sparc\0\0"
+
+typedef u32 compat_size_t;
+typedef s32 compat_ssize_t;
+typedef s32 compat_time_t;
+typedef s32 compat_clock_t;
+typedef s32 compat_pid_t;
+typedef u16 __compat_uid_t;
+typedef u16 __compat_gid_t;
+typedef u32 __compat_uid32_t;
+typedef u32 __compat_gid32_t;
+typedef u16 compat_mode_t;
+typedef u32 compat_ino_t;
+typedef u16 compat_dev_t;
+typedef s32 compat_off_t;
+typedef s64 compat_loff_t;
+typedef s16 compat_nlink_t;
+typedef u16 compat_ipc_pid_t;
+typedef s32 compat_daddr_t;
+typedef u32 compat_caddr_t;
+typedef __kernel_fsid_t compat_fsid_t;
+typedef s32 compat_key_t;
+typedef s32 compat_timer_t;
+
+typedef s32 compat_int_t;
+typedef s32 compat_long_t;
+typedef s64 compat_s64;
+typedef u32 compat_uint_t;
+typedef u32 compat_ulong_t;
+typedef u64 compat_u64;
+typedef u32 compat_uptr_t;
+
+struct compat_timespec {
+ compat_time_t tv_sec;
+ s32 tv_nsec;
+};
+
+struct compat_timeval {
+ compat_time_t tv_sec;
+ s32 tv_usec;
+};
+
+struct compat_stat {
+ compat_dev_t st_dev;
+ compat_ino_t st_ino;
+ compat_mode_t st_mode;
+ compat_nlink_t st_nlink;
+ __compat_uid_t st_uid;
+ __compat_gid_t st_gid;
+ compat_dev_t st_rdev;
+ compat_off_t st_size;
+ compat_time_t st_atime;
+ compat_ulong_t st_atime_nsec;
+ compat_time_t st_mtime;
+ compat_ulong_t st_mtime_nsec;
+ compat_time_t st_ctime;
+ compat_ulong_t st_ctime_nsec;
+ compat_off_t st_blksize;
+ compat_off_t st_blocks;
+ u32 __unused4[2];
+};
+
+struct compat_stat64 {
+ unsigned long long st_dev;
+
+ unsigned long long st_ino;
+
+ unsigned int st_mode;
+ unsigned int st_nlink;
+
+ unsigned int st_uid;
+ unsigned int st_gid;
+
+ unsigned long long st_rdev;
+
+ unsigned char __pad3[8];
+
+ long long st_size;
+ unsigned int st_blksize;
+
+ unsigned char __pad4[8];
+ unsigned int st_blocks;
+
+ unsigned int st_atime;
+ unsigned int st_atime_nsec;
+
+ unsigned int st_mtime;
+ unsigned int st_mtime_nsec;
+
+ unsigned int st_ctime;
+ unsigned int st_ctime_nsec;
+
+ unsigned int __unused4;
+ unsigned int __unused5;
+};
+
+struct compat_flock {
+ short l_type;
+ short l_whence;
+ compat_off_t l_start;
+ compat_off_t l_len;
+ compat_pid_t l_pid;
+ short __unused;
+};
+
+#define F_GETLK64 12
+#define F_SETLK64 13
+#define F_SETLKW64 14
+
+struct compat_flock64 {
+ short l_type;
+ short l_whence;
+ compat_loff_t l_start;
+ compat_loff_t l_len;
+ compat_pid_t l_pid;
+ short __unused;
+};
+
+struct compat_statfs {
+ int f_type;
+ int f_bsize;
+ int f_blocks;
+ int f_bfree;
+ int f_bavail;
+ int f_files;
+ int f_ffree;
+ compat_fsid_t f_fsid;
+ int f_namelen; /* SunOS ignores this field. */
+ int f_frsize;
+ int f_flags;
+ int f_spare[4];
+};
+
+#define COMPAT_RLIM_INFINITY 0x7fffffff
+
+typedef u32 compat_old_sigset_t;
+
+#define _COMPAT_NSIG 64
+#define _COMPAT_NSIG_BPW 32
+
+typedef u32 compat_sigset_word;
+
+typedef union compat_sigval {
+ compat_int_t sival_int;
+ compat_uptr_t sival_ptr;
+} compat_sigval_t;
+
+#define SI_PAD_SIZE32 (128/sizeof(int) - 3)
+
+typedef struct compat_siginfo {
+ int si_signo;
+ int si_errno;
+ int si_code;
+
+ union {
+ int _pad[SI_PAD_SIZE32];
+
+ /* kill() */
+ struct {
+ compat_pid_t _pid; /* sender's pid */
+ unsigned int _uid; /* sender's uid */
+ } _kill;
+
+ /* POSIX.1b timers */
+ struct {
+ compat_timer_t _tid; /* timer id */
+ int _overrun; /* overrun count */
+ compat_sigval_t _sigval; /* same as below */
+ int _sys_private; /* not to be passed to user */
+ } _timer;
+
+ /* POSIX.1b signals */
+ struct {
+ compat_pid_t _pid; /* sender's pid */
+ unsigned int _uid; /* sender's uid */
+ compat_sigval_t _sigval;
+ } _rt;
+
+ /* SIGCHLD */
+ struct {
+ compat_pid_t _pid; /* which child */
+ unsigned int _uid; /* sender's uid */
+ int _status; /* exit code */
+ compat_clock_t _utime;
+ compat_clock_t _stime;
+ } _sigchld;
+
+ /* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGEMT */
+ struct {
+ u32 _addr; /* faulting insn/memory ref. */
+ int _trapno;
+ } _sigfault;
+
+ /* SIGPOLL */
+ struct {
+ int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
+ int _fd;
+ } _sigpoll;
+ } _sifields;
+} compat_siginfo_t;
+
+#define COMPAT_OFF_T_MAX 0x7fffffff
+#define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL
+
+/*
+ * A pointer passed in from user mode. This should not
+ * be used for syscall parameters, just declare them
+ * as pointers because the syscall entry code will have
+ * appropriately converted them already.
+ */
+
+static inline void __user *compat_ptr(compat_uptr_t uptr)
+{
+ return (void __user *)(unsigned long)uptr;
+}
+
+static inline compat_uptr_t ptr_to_compat(void __user *uptr)
+{
+ return (u32)(unsigned long)uptr;
+}
+
+static inline void __user *arch_compat_alloc_user_space(long len)
+{
+ struct pt_regs *regs = current_thread_info()->kregs;
+ unsigned long usp = regs->u_regs[UREG_I6];
+
+ if (test_thread_64bit_stack(usp))
+ usp += STACK_BIAS;
+
+ if (test_thread_flag(TIF_32BIT))
+ usp &= 0xffffffffUL;
+
+ usp -= len;
+ usp &= ~0x7UL;
+
+ return (void __user *) usp;
+}
+
+struct compat_ipc64_perm {
+ compat_key_t key;
+ __compat_uid32_t uid;
+ __compat_gid32_t gid;
+ __compat_uid32_t cuid;
+ __compat_gid32_t cgid;
+ unsigned short __pad1;
+ compat_mode_t mode;
+ unsigned short __pad2;
+ unsigned short seq;
+ unsigned long __unused1; /* yes they really are 64bit pads */
+ unsigned long __unused2;
+};
+
+struct compat_semid64_ds {
+ struct compat_ipc64_perm sem_perm;
+ unsigned int __pad1;
+ compat_time_t sem_otime;
+ unsigned int __pad2;
+ compat_time_t sem_ctime;
+ u32 sem_nsems;
+ u32 __unused1;
+ u32 __unused2;
+};
+
+struct compat_msqid64_ds {
+ struct compat_ipc64_perm msg_perm;
+ unsigned int __pad1;
+ compat_time_t msg_stime;
+ unsigned int __pad2;
+ compat_time_t msg_rtime;
+ unsigned int __pad3;
+ compat_time_t msg_ctime;
+ unsigned int msg_cbytes;
+ unsigned int msg_qnum;
+ unsigned int msg_qbytes;
+ compat_pid_t msg_lspid;
+ compat_pid_t msg_lrpid;
+ unsigned int __unused1;
+ unsigned int __unused2;
+};
+
+struct compat_shmid64_ds {
+ struct compat_ipc64_perm shm_perm;
+ unsigned int __pad1;
+ compat_time_t shm_atime;
+ unsigned int __pad2;
+ compat_time_t shm_dtime;
+ unsigned int __pad3;
+ compat_time_t shm_ctime;
+ compat_size_t shm_segsz;
+ compat_pid_t shm_cpid;
+ compat_pid_t shm_lpid;
+ unsigned int shm_nattch;
+ unsigned int __unused1;
+ unsigned int __unused2;
+};
+
+static inline int is_compat_task(void)
+{
+ return test_thread_flag(TIF_32BIT);
+}
+
+#endif /* _ASM_SPARC64_COMPAT_H */
diff --git a/arch/sparc/include/asm/compat_signal.h b/arch/sparc/include/asm/compat_signal.h
new file mode 100644
index 00000000000..9ed1f128b4d
--- /dev/null
+++ b/arch/sparc/include/asm/compat_signal.h
@@ -0,0 +1,23 @@
+#ifndef _COMPAT_SIGNAL_H
+#define _COMPAT_SIGNAL_H
+
+#include <linux/compat.h>
+#include <asm/signal.h>
+
+#ifdef CONFIG_COMPAT
+struct __new_sigaction32 {
+ unsigned sa_handler;
+ unsigned int sa_flags;
+ unsigned sa_restorer; /* not used by Linux/SPARC yet */
+ compat_sigset_t sa_mask;
+};
+
+struct __old_sigaction32 {
+ unsigned sa_handler;
+ compat_old_sigset_t sa_mask;
+ unsigned int sa_flags;
+ unsigned sa_restorer; /* not used by Linux/SPARC yet */
+};
+#endif
+
+#endif /* !(_COMPAT_SIGNAL_H) */
diff --git a/arch/sparc/include/asm/contregs.h b/arch/sparc/include/asm/contregs.h
new file mode 100644
index 00000000000..b8abdfcf555
--- /dev/null
+++ b/arch/sparc/include/asm/contregs.h
@@ -0,0 +1,31 @@
+#ifndef _SPARC_CONTREGS_H
+#define _SPARC_CONTREGS_H
+
+/* contregs.h: Addresses of registers in the ASI_CONTROL alternate address
+ * space. These are for the mmu's context register, etc.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+/* s=Swift, h=Ross_HyperSPARC, v=TI_Viking, t=Tsunami, r=Ross_Cypress */
+#define AC_M_PCR 0x0000 /* shv Processor Control Reg */
+#define AC_M_CTPR 0x0100 /* shv Context Table Pointer Reg */
+#define AC_M_CXR 0x0200 /* shv Context Register */
+#define AC_M_SFSR 0x0300 /* shv Synchronous Fault Status Reg */
+#define AC_M_SFAR 0x0400 /* shv Synchronous Fault Address Reg */
+#define AC_M_AFSR 0x0500 /* hv Asynchronous Fault Status Reg */
+#define AC_M_AFAR 0x0600 /* hv Asynchronous Fault Address Reg */
+#define AC_M_RESET 0x0700 /* hv Reset Reg */
+#define AC_M_RPR 0x1000 /* hv Root Pointer Reg */
+#define AC_M_TSUTRCR 0x1000 /* s TLB Replacement Ctrl Reg */
+#define AC_M_IAPTP 0x1100 /* hv Instruction Access PTP */
+#define AC_M_DAPTP 0x1200 /* hv Data Access PTP */
+#define AC_M_ITR 0x1300 /* hv Index Tag Register */
+#define AC_M_TRCR 0x1400 /* hv TLB Replacement Control Reg */
+#define AC_M_SFSRX 0x1300 /* s Synch Fault Status Reg prim */
+#define AC_M_SFARX 0x1400 /* s Synch Fault Address Reg prim */
+#define AC_M_RPR1 0x1500 /* h Root Pointer Reg (entry 2) */
+#define AC_M_IAPTP1 0x1600 /* h Instruction Access PTP (entry 2) */
+#define AC_M_DAPTP1 0x1700 /* h Data Access PTP (entry 2) */
+
+#endif /* _SPARC_CONTREGS_H */
diff --git a/arch/sparc/include/asm/cpu_type.h b/arch/sparc/include/asm/cpu_type.h
new file mode 100644
index 00000000000..84d7d83b808
--- /dev/null
+++ b/arch/sparc/include/asm/cpu_type.h
@@ -0,0 +1,28 @@
+#ifndef __ASM_CPU_TYPE_H
+#define __ASM_CPU_TYPE_H
+
+/*
+ * Sparc (general) CPU types
+ */
+enum sparc_cpu {
+ sun4m = 0x00,
+ sun4d = 0x01,
+ sun4e = 0x02,
+ sun4u = 0x03, /* V8 ploos ploos */
+ sun_unknown = 0x04,
+ ap1000 = 0x05, /* almost a sun4m */
+ sparc_leon = 0x06, /* Leon SoC */
+};
+
+#ifdef CONFIG_SPARC32
+extern enum sparc_cpu sparc_cpu_model;
+
+#define SUN4M_NCPUS 4 /* Architectural limit of sun4m. */
+
+#else
+
+#define sparc_cpu_model sun4u
+
+#endif
+
+#endif /* __ASM_CPU_TYPE_H */
diff --git a/arch/sparc/include/asm/cpudata.h b/arch/sparc/include/asm/cpudata.h
new file mode 100644
index 00000000000..128b56b0867
--- /dev/null
+++ b/arch/sparc/include/asm/cpudata.h
@@ -0,0 +1,18 @@
+#ifndef ___ASM_SPARC_CPUDATA_H
+#define ___ASM_SPARC_CPUDATA_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/threads.h>
+#include <linux/percpu.h>
+
+extern const struct seq_operations cpuinfo_op;
+
+#endif /* !(__ASSEMBLY__) */
+
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/cpudata_64.h>
+#else
+#include <asm/cpudata_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/cpudata_32.h b/arch/sparc/include/asm/cpudata_32.h
new file mode 100644
index 00000000000..0300d94c25b
--- /dev/null
+++ b/arch/sparc/include/asm/cpudata_32.h
@@ -0,0 +1,31 @@
+/* cpudata.h: Per-cpu parameters.
+ *
+ * Copyright (C) 2004 Keith M Wesolowski (wesolows@foobazco.org)
+ *
+ * Based on include/asm/cpudata.h and Linux 2.4 smp.h
+ * both (C) David S. Miller.
+ */
+
+#ifndef _SPARC_CPUDATA_H
+#define _SPARC_CPUDATA_H
+
+#include <linux/percpu.h>
+
+typedef struct {
+ unsigned long udelay_val;
+ unsigned long clock_tick;
+ unsigned int counter;
+#ifdef CONFIG_SMP
+ unsigned int irq_resched_count;
+ unsigned int irq_call_count;
+#endif
+ int prom_node;
+ int mid;
+ int next;
+} cpuinfo_sparc;
+
+DECLARE_PER_CPU(cpuinfo_sparc, __cpu_data);
+#define cpu_data(__cpu) per_cpu(__cpu_data, (__cpu))
+#define local_cpu_data() __get_cpu_var(__cpu_data)
+
+#endif /* _SPARC_CPUDATA_H */
diff --git a/arch/sparc/include/asm/cpudata_64.h b/arch/sparc/include/asm/cpudata_64.h
new file mode 100644
index 00000000000..0e594076912
--- /dev/null
+++ b/arch/sparc/include/asm/cpudata_64.h
@@ -0,0 +1,39 @@
+/* cpudata.h: Per-cpu parameters.
+ *
+ * Copyright (C) 2003, 2005, 2006 David S. Miller (davem@davemloft.net)
+ */
+
+#ifndef _SPARC64_CPUDATA_H
+#define _SPARC64_CPUDATA_H
+
+#ifndef __ASSEMBLY__
+
+typedef struct {
+ /* Dcache line 1 */
+ unsigned int __softirq_pending; /* must be 1st, see rtrap.S */
+ unsigned int __nmi_count;
+ unsigned long clock_tick; /* %tick's per second */
+ unsigned long __pad;
+ unsigned int irq0_irqs;
+ unsigned int __pad2;
+
+ /* Dcache line 2, rarely used */
+ unsigned int dcache_size;
+ unsigned int dcache_line_size;
+ unsigned int icache_size;
+ unsigned int icache_line_size;
+ unsigned int ecache_size;
+ unsigned int ecache_line_size;
+ int core_id;
+ int proc_id;
+} cpuinfo_sparc;
+
+DECLARE_PER_CPU(cpuinfo_sparc, __cpu_data);
+#define cpu_data(__cpu) per_cpu(__cpu_data, (__cpu))
+#define local_cpu_data() __get_cpu_var(__cpu_data)
+
+#endif /* !(__ASSEMBLY__) */
+
+#include <asm/trap_block.h>
+
+#endif /* _SPARC64_CPUDATA_H */
diff --git a/arch/sparc/include/asm/current.h b/arch/sparc/include/asm/current.h
new file mode 100644
index 00000000000..10a0df55a57
--- /dev/null
+++ b/arch/sparc/include/asm/current.h
@@ -0,0 +1,34 @@
+/* include/asm/current.h
+ *
+ * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright (C) 2002 Pete Zaitcev (zaitcev@yahoo.com)
+ * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
+ *
+ * Derived from "include/asm-s390/current.h" by
+ * Martin Schwidefsky (schwidefsky@de.ibm.com)
+ * Derived from "include/asm-i386/current.h"
+*/
+#ifndef _SPARC_CURRENT_H
+#define _SPARC_CURRENT_H
+
+#include <linux/thread_info.h>
+
+#ifdef CONFIG_SPARC64
+register struct task_struct *current asm("g4");
+#endif
+
+#ifdef CONFIG_SPARC32
+/* We might want to consider using %g4 like sparc64 to shave a few cycles.
+ *
+ * Two stage process (inline + #define) for type-checking.
+ * We also obfuscate get_current() to check if anyone used that by mistake.
+ */
+struct task_struct;
+static inline struct task_struct *__get_current(void)
+{
+ return current_thread_info()->task;
+}
+#define current __get_current()
+#endif
+
+#endif /* !(_SPARC_CURRENT_H) */
diff --git a/arch/sparc/include/asm/dcr.h b/arch/sparc/include/asm/dcr.h
new file mode 100644
index 00000000000..620c9ba642e
--- /dev/null
+++ b/arch/sparc/include/asm/dcr.h
@@ -0,0 +1,14 @@
+#ifndef _SPARC64_DCR_H
+#define _SPARC64_DCR_H
+
+/* UltraSparc-III/III+ Dispatch Control Register, ASR 0x12 */
+#define DCR_DPE 0x0000000000001000 /* III+: D$ Parity Error Enable */
+#define DCR_OBS 0x0000000000000fc0 /* Observability Bus Controls */
+#define DCR_BPE 0x0000000000000020 /* Branch Predict Enable */
+#define DCR_RPE 0x0000000000000010 /* Return Address Prediction Enable */
+#define DCR_SI 0x0000000000000008 /* Single Instruction Disable */
+#define DCR_IPE 0x0000000000000004 /* III+: I$ Parity Error Enable */
+#define DCR_IFPOE 0x0000000000000002 /* IRQ FP Operation Enable */
+#define DCR_MS 0x0000000000000001 /* Multi-Scalar dispatch */
+
+#endif /* _SPARC64_DCR_H */
diff --git a/arch/sparc/include/asm/dcu.h b/arch/sparc/include/asm/dcu.h
new file mode 100644
index 00000000000..0f704e106a1
--- /dev/null
+++ b/arch/sparc/include/asm/dcu.h
@@ -0,0 +1,27 @@
+#ifndef _SPARC64_DCU_H
+#define _SPARC64_DCU_H
+
+#include <linux/const.h>
+
+/* UltraSparc-III Data Cache Unit Control Register */
+#define DCU_CP _AC(0x0002000000000000,UL) /* Phys Cache Enable w/o mmu */
+#define DCU_CV _AC(0x0001000000000000,UL) /* Virt Cache Enable w/o mmu */
+#define DCU_ME _AC(0x0000800000000000,UL) /* NC-store Merging Enable */
+#define DCU_RE _AC(0x0000400000000000,UL) /* RAW bypass Enable */
+#define DCU_PE _AC(0x0000200000000000,UL) /* PCache Enable */
+#define DCU_HPE _AC(0x0000100000000000,UL) /* HW prefetch Enable */
+#define DCU_SPE _AC(0x0000080000000000,UL) /* SW prefetch Enable */
+#define DCU_SL _AC(0x0000040000000000,UL) /* Secondary ld-steering Enab*/
+#define DCU_WE _AC(0x0000020000000000,UL) /* WCache enable */
+#define DCU_PM _AC(0x000001fe00000000,UL) /* PA Watchpoint Byte Mask */
+#define DCU_VM _AC(0x00000001fe000000,UL) /* VA Watchpoint Byte Mask */
+#define DCU_PR _AC(0x0000000001000000,UL) /* PA Watchpoint Read Enable */
+#define DCU_PW _AC(0x0000000000800000,UL) /* PA Watchpoint Write Enable*/
+#define DCU_VR _AC(0x0000000000400000,UL) /* VA Watchpoint Read Enable */
+#define DCU_VW _AC(0x0000000000200000,UL) /* VA Watchpoint Write Enable*/
+#define DCU_DM _AC(0x0000000000000008,UL) /* DMMU Enable */
+#define DCU_IM _AC(0x0000000000000004,UL) /* IMMU Enable */
+#define DCU_DC _AC(0x0000000000000002,UL) /* Data Cache Enable */
+#define DCU_IC _AC(0x0000000000000001,UL) /* Instruction Cache Enable */
+
+#endif /* _SPARC64_DCU_H */
diff --git a/arch/sparc/include/asm/delay.h b/arch/sparc/include/asm/delay.h
new file mode 100644
index 00000000000..467caa2a97a
--- /dev/null
+++ b/arch/sparc/include/asm/delay.h
@@ -0,0 +1,8 @@
+#ifndef ___ASM_SPARC_DELAY_H
+#define ___ASM_SPARC_DELAY_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/delay_64.h>
+#else
+#include <asm/delay_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/delay_32.h b/arch/sparc/include/asm/delay_32.h
new file mode 100644
index 00000000000..3fb8ca144b4
--- /dev/null
+++ b/arch/sparc/include/asm/delay_32.h
@@ -0,0 +1,34 @@
+/*
+ * delay.h: Linux delay routines on the Sparc.
+ *
+ * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu).
+ */
+
+#ifndef __SPARC_DELAY_H
+#define __SPARC_DELAY_H
+
+#include <asm/cpudata.h>
+
+static inline void __delay(unsigned long loops)
+{
+ __asm__ __volatile__("cmp %0, 0\n\t"
+ "1: bne 1b\n\t"
+ "subcc %0, 1, %0\n" :
+ "=&r" (loops) :
+ "0" (loops) :
+ "cc");
+}
+
+/* This is too messy with inline asm on the Sparc. */
+void __udelay(unsigned long usecs, unsigned long lpj);
+void __ndelay(unsigned long nsecs, unsigned long lpj);
+
+#ifdef CONFIG_SMP
+#define __udelay_val cpu_data(smp_processor_id()).udelay_val
+#else /* SMP */
+#define __udelay_val loops_per_jiffy
+#endif /* SMP */
+#define udelay(__usecs) __udelay(__usecs, __udelay_val)
+#define ndelay(__nsecs) __ndelay(__nsecs, __udelay_val)
+
+#endif /* defined(__SPARC_DELAY_H) */
diff --git a/arch/sparc/include/asm/delay_64.h b/arch/sparc/include/asm/delay_64.h
new file mode 100644
index 00000000000..0ba5424856d
--- /dev/null
+++ b/arch/sparc/include/asm/delay_64.h
@@ -0,0 +1,17 @@
+/* delay.h: Linux delay routines on sparc64.
+ *
+ * Copyright (C) 1996, 2004, 2007 David S. Miller (davem@davemloft.net).
+ */
+
+#ifndef _SPARC64_DELAY_H
+#define _SPARC64_DELAY_H
+
+#ifndef __ASSEMBLY__
+
+void __delay(unsigned long loops);
+void udelay(unsigned long usecs);
+#define mdelay(n) udelay((n) * 1000)
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _SPARC64_DELAY_H */
diff --git a/arch/sparc/include/asm/device.h b/arch/sparc/include/asm/device.h
new file mode 100644
index 00000000000..bb3f0b0c675
--- /dev/null
+++ b/arch/sparc/include/asm/device.h
@@ -0,0 +1,30 @@
+/*
+ * Arch specific extensions to struct device
+ *
+ * This file is released under the GPLv2
+ */
+#ifndef _ASM_SPARC_DEVICE_H
+#define _ASM_SPARC_DEVICE_H
+
+#include <asm/openprom.h>
+
+struct device_node;
+struct platform_device;
+
+struct dev_archdata {
+ void *iommu;
+ void *stc;
+ void *host_controller;
+ struct platform_device *op;
+ int numa_node;
+};
+
+void of_propagate_archdata(struct platform_device *bus);
+
+struct pdev_archdata {
+ struct resource resource[PROMREG_MAX];
+ unsigned int irqs[PROMINTR_MAX];
+ int num_irqs;
+};
+
+#endif /* _ASM_SPARC_DEVICE_H */
diff --git a/arch/sparc/include/asm/dma-mapping.h b/arch/sparc/include/asm/dma-mapping.h
new file mode 100644
index 00000000000..1ee02710b2d
--- /dev/null
+++ b/arch/sparc/include/asm/dma-mapping.h
@@ -0,0 +1,79 @@
+#ifndef ___ASM_SPARC_DMA_MAPPING_H
+#define ___ASM_SPARC_DMA_MAPPING_H
+
+#include <linux/scatterlist.h>
+#include <linux/mm.h>
+#include <linux/dma-debug.h>
+
+#define DMA_ERROR_CODE (~(dma_addr_t)0x0)
+
+int dma_supported(struct device *dev, u64 mask);
+
+#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
+#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+
+extern struct dma_map_ops *dma_ops;
+extern struct dma_map_ops *leon_dma_ops;
+extern struct dma_map_ops pci32_dma_ops;
+
+extern struct bus_type pci_bus_type;
+
+static inline struct dma_map_ops *get_dma_ops(struct device *dev)
+{
+#if defined(CONFIG_SPARC32) && defined(CONFIG_PCI)
+ if (sparc_cpu_model == sparc_leon)
+ return leon_dma_ops;
+ else if (dev->bus == &pci_bus_type)
+ return &pci32_dma_ops;
+#endif
+ return dma_ops;
+}
+
+#include <asm-generic/dma-mapping-common.h>
+
+#define dma_alloc_coherent(d,s,h,f) dma_alloc_attrs(d,s,h,f,NULL)
+
+static inline void *dma_alloc_attrs(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t flag,
+ struct dma_attrs *attrs)
+{
+ struct dma_map_ops *ops = get_dma_ops(dev);
+ void *cpu_addr;
+
+ cpu_addr = ops->alloc(dev, size, dma_handle, flag, attrs);
+ debug_dma_alloc_coherent(dev, size, *dma_handle, cpu_addr);
+ return cpu_addr;
+}
+
+#define dma_free_coherent(d,s,c,h) dma_free_attrs(d,s,c,h,NULL)
+
+static inline void dma_free_attrs(struct device *dev, size_t size,
+ void *cpu_addr, dma_addr_t dma_handle,
+ struct dma_attrs *attrs)
+{
+ struct dma_map_ops *ops = get_dma_ops(dev);
+
+ debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
+ ops->free(dev, size, cpu_addr, dma_handle, attrs);
+}
+
+static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
+{
+ debug_dma_mapping_error(dev, dma_addr);
+ return (dma_addr == DMA_ERROR_CODE);
+}
+
+static inline int dma_set_mask(struct device *dev, u64 mask)
+{
+#ifdef CONFIG_PCI
+ if (dev->bus == &pci_bus_type) {
+ if (!dev->dma_mask || !dma_supported(dev, mask))
+ return -EINVAL;
+ *dev->dma_mask = mask;
+ return 0;
+ }
+#endif
+ return -EINVAL;
+}
+
+#endif
diff --git a/arch/sparc/include/asm/dma.h b/arch/sparc/include/asm/dma.h
new file mode 100644
index 00000000000..3d434ef5eae
--- /dev/null
+++ b/arch/sparc/include/asm/dma.h
@@ -0,0 +1,143 @@
+#ifndef _ASM_SPARC_DMA_H
+#define _ASM_SPARC_DMA_H
+
+/* These are irrelevant for Sparc DMA, but we leave it in so that
+ * things can compile.
+ */
+#define MAX_DMA_CHANNELS 8
+#define DMA_MODE_READ 1
+#define DMA_MODE_WRITE 2
+#define MAX_DMA_ADDRESS (~0UL)
+
+/* Useful constants */
+#define SIZE_16MB (16*1024*1024)
+#define SIZE_64K (64*1024)
+
+/* SBUS DMA controller reg offsets */
+#define DMA_CSR 0x00UL /* rw DMA control/status register 0x00 */
+#define DMA_ADDR 0x04UL /* rw DMA transfer address register 0x04 */
+#define DMA_COUNT 0x08UL /* rw DMA transfer count register 0x08 */
+#define DMA_TEST 0x0cUL /* rw DMA test/debug register 0x0c */
+
+/* Fields in the cond_reg register */
+/* First, the version identification bits */
+#define DMA_DEVICE_ID 0xf0000000 /* Device identification bits */
+#define DMA_VERS0 0x00000000 /* Sunray DMA version */
+#define DMA_ESCV1 0x40000000 /* DMA ESC Version 1 */
+#define DMA_VERS1 0x80000000 /* DMA rev 1 */
+#define DMA_VERS2 0xa0000000 /* DMA rev 2 */
+#define DMA_VERHME 0xb0000000 /* DMA hme gate array */
+#define DMA_VERSPLUS 0x90000000 /* DMA rev 1 PLUS */
+
+#define DMA_HNDL_INTR 0x00000001 /* An IRQ needs to be handled */
+#define DMA_HNDL_ERROR 0x00000002 /* We need to take an error */
+#define DMA_FIFO_ISDRAIN 0x0000000c /* The DMA FIFO is draining */
+#define DMA_INT_ENAB 0x00000010 /* Turn on interrupts */
+#define DMA_FIFO_INV 0x00000020 /* Invalidate the FIFO */
+#define DMA_ACC_SZ_ERR 0x00000040 /* The access size was bad */
+#define DMA_FIFO_STDRAIN 0x00000040 /* DMA_VERS1 Drain the FIFO */
+#define DMA_RST_SCSI 0x00000080 /* Reset the SCSI controller */
+#define DMA_RST_ENET DMA_RST_SCSI /* Reset the ENET controller */
+#define DMA_ST_WRITE 0x00000100 /* write from device to memory */
+#define DMA_ENABLE 0x00000200 /* Fire up DMA, handle requests */
+#define DMA_PEND_READ 0x00000400 /* DMA_VERS1/0/PLUS Pending Read */
+#define DMA_ESC_BURST 0x00000800 /* 1=16byte 0=32byte */
+#define DMA_READ_AHEAD 0x00001800 /* DMA read ahead partial longword */
+#define DMA_DSBL_RD_DRN 0x00001000 /* No EC drain on slave reads */
+#define DMA_BCNT_ENAB 0x00002000 /* If on, use the byte counter */
+#define DMA_TERM_CNTR 0x00004000 /* Terminal counter */
+#define DMA_SCSI_SBUS64 0x00008000 /* HME: Enable 64-bit SBUS mode. */
+#define DMA_CSR_DISAB 0x00010000 /* No FIFO drains during csr */
+#define DMA_SCSI_DISAB 0x00020000 /* No FIFO drains during reg */
+#define DMA_DSBL_WR_INV 0x00020000 /* No EC inval. on slave writes */
+#define DMA_ADD_ENABLE 0x00040000 /* Special ESC DVMA optimization */
+#define DMA_E_BURSTS 0x000c0000 /* ENET: SBUS r/w burst mask */
+#define DMA_E_BURST32 0x00040000 /* ENET: SBUS 32 byte r/w burst */
+#define DMA_E_BURST16 0x00000000 /* ENET: SBUS 16 byte r/w burst */
+#define DMA_BRST_SZ 0x000c0000 /* SCSI: SBUS r/w burst size */
+#define DMA_BRST64 0x000c0000 /* SCSI: 64byte bursts (HME on UltraSparc only) */
+#define DMA_BRST32 0x00040000 /* SCSI: 32byte bursts */
+#define DMA_BRST16 0x00000000 /* SCSI: 16byte bursts */
+#define DMA_BRST0 0x00080000 /* SCSI: no bursts (non-HME gate arrays) */
+#define DMA_ADDR_DISAB 0x00100000 /* No FIFO drains during addr */
+#define DMA_2CLKS 0x00200000 /* Each transfer = 2 clock ticks */
+#define DMA_3CLKS 0x00400000 /* Each transfer = 3 clock ticks */
+#define DMA_EN_ENETAUI DMA_3CLKS /* Put lance into AUI-cable mode */
+#define DMA_CNTR_DISAB 0x00800000 /* No IRQ when DMA_TERM_CNTR set */
+#define DMA_AUTO_NADDR 0x01000000 /* Use "auto nxt addr" feature */
+#define DMA_SCSI_ON 0x02000000 /* Enable SCSI dma */
+#define DMA_PARITY_OFF 0x02000000 /* HME: disable parity checking */
+#define DMA_LOADED_ADDR 0x04000000 /* Address has been loaded */
+#define DMA_LOADED_NADDR 0x08000000 /* Next address has been loaded */
+#define DMA_RESET_FAS366 0x08000000 /* HME: Assert RESET to FAS366 */
+
+/* Values describing the burst-size property from the PROM */
+#define DMA_BURST1 0x01
+#define DMA_BURST2 0x02
+#define DMA_BURST4 0x04
+#define DMA_BURST8 0x08
+#define DMA_BURST16 0x10
+#define DMA_BURST32 0x20
+#define DMA_BURST64 0x40
+#define DMA_BURSTBITS 0x7f
+
+/* From PCI */
+
+#ifdef CONFIG_PCI
+extern int isa_dma_bridge_buggy;
+#else
+#define isa_dma_bridge_buggy (0)
+#endif
+
+#ifdef CONFIG_SPARC32
+
+/* Routines for data transfer buffers. */
+struct device;
+struct scatterlist;
+
+struct sparc32_dma_ops {
+ __u32 (*get_scsi_one)(struct device *, char *, unsigned long);
+ void (*get_scsi_sgl)(struct device *, struct scatterlist *, int);
+ void (*release_scsi_one)(struct device *, __u32, unsigned long);
+ void (*release_scsi_sgl)(struct device *, struct scatterlist *,int);
+#ifdef CONFIG_SBUS
+ int (*map_dma_area)(struct device *, dma_addr_t *, unsigned long, unsigned long, int);
+ void (*unmap_dma_area)(struct device *, unsigned long, int);
+#endif
+};
+extern const struct sparc32_dma_ops *sparc32_dma_ops;
+
+#define mmu_get_scsi_one(dev,vaddr,len) \
+ sparc32_dma_ops->get_scsi_one(dev, vaddr, len)
+#define mmu_get_scsi_sgl(dev,sg,sz) \
+ sparc32_dma_ops->get_scsi_sgl(dev, sg, sz)
+#define mmu_release_scsi_one(dev,vaddr,len) \
+ sparc32_dma_ops->release_scsi_one(dev, vaddr,len)
+#define mmu_release_scsi_sgl(dev,sg,sz) \
+ sparc32_dma_ops->release_scsi_sgl(dev, sg, sz)
+
+#ifdef CONFIG_SBUS
+/*
+ * mmu_map/unmap are provided by iommu/iounit; Invalid to call on IIep.
+ *
+ * The mmu_map_dma_area establishes two mappings in one go.
+ * These mappings point to pages normally mapped at 'va' (linear address).
+ * First mapping is for CPU visible address at 'a', uncached.
+ * This is an alias, but it works because it is an uncached mapping.
+ * Second mapping is for device visible address, or "bus" address.
+ * The bus address is returned at '*pba'.
+ *
+ * These functions seem distinct, but are hard to split.
+ * On sun4m, page attributes depend on the CPU type, so we have to
+ * know if we are mapping RAM or I/O, so it has to be an additional argument
+ * to a separate mapping function for CPU visible mappings.
+ */
+#define sbus_map_dma_area(dev,pba,va,a,len) \
+ sparc32_dma_ops->map_dma_area(dev, pba, va, a, len)
+#define sbus_unmap_dma_area(dev,ba,len) \
+ sparc32_dma_ops->unmap_dma_area(dev, ba, len)
+#endif /* CONFIG_SBUS */
+
+#endif
+
+#endif /* !(_ASM_SPARC_DMA_H) */
diff --git a/arch/sparc/include/asm/ebus_dma.h b/arch/sparc/include/asm/ebus_dma.h
new file mode 100644
index 00000000000..fcfb4948147
--- /dev/null
+++ b/arch/sparc/include/asm/ebus_dma.h
@@ -0,0 +1,35 @@
+#ifndef __ASM_SPARC_EBUS_DMA_H
+#define __ASM_SPARC_EBUS_DMA_H
+
+struct ebus_dma_info {
+ spinlock_t lock;
+ void __iomem *regs;
+
+ unsigned int flags;
+#define EBUS_DMA_FLAG_USE_EBDMA_HANDLER 0x00000001
+#define EBUS_DMA_FLAG_TCI_DISABLE 0x00000002
+
+ /* These are only valid is EBUS_DMA_FLAG_USE_EBDMA_HANDLER is
+ * set.
+ */
+ void (*callback)(struct ebus_dma_info *p, int event, void *cookie);
+ void *client_cookie;
+ unsigned int irq;
+#define EBUS_DMA_EVENT_ERROR 1
+#define EBUS_DMA_EVENT_DMA 2
+#define EBUS_DMA_EVENT_DEVICE 4
+
+ unsigned char name[64];
+};
+
+int ebus_dma_register(struct ebus_dma_info *p);
+int ebus_dma_irq_enable(struct ebus_dma_info *p, int on);
+void ebus_dma_unregister(struct ebus_dma_info *p);
+int ebus_dma_request(struct ebus_dma_info *p, dma_addr_t bus_addr,
+ size_t len);
+void ebus_dma_prepare(struct ebus_dma_info *p, int write);
+unsigned int ebus_dma_residue(struct ebus_dma_info *p);
+unsigned int ebus_dma_addr(struct ebus_dma_info *p);
+void ebus_dma_enable(struct ebus_dma_info *p, int on);
+
+#endif /* __ASM_SPARC_EBUS_DMA_H */
diff --git a/arch/sparc/include/asm/ecc.h b/arch/sparc/include/asm/ecc.h
new file mode 100644
index 00000000000..ccb84b66fef
--- /dev/null
+++ b/arch/sparc/include/asm/ecc.h
@@ -0,0 +1,122 @@
+/*
+ * ecc.h: Definitions and defines for the external cache/memory
+ * controller on the sun4m.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _SPARC_ECC_H
+#define _SPARC_ECC_H
+
+/* These registers are accessed through the SRMMU passthrough ASI 0x20 */
+#define ECC_ENABLE 0x00000000 /* ECC enable register */
+#define ECC_FSTATUS 0x00000008 /* ECC fault status register */
+#define ECC_FADDR 0x00000010 /* ECC fault address register */
+#define ECC_DIGNOSTIC 0x00000018 /* ECC diagnostics register */
+#define ECC_MBAENAB 0x00000020 /* MBus arbiter enable register */
+#define ECC_DMESG 0x00001000 /* Diagnostic message passing area */
+
+/* ECC MBus Arbiter Enable register:
+ *
+ * ----------------------------------------
+ * | |SBUS|MOD3|MOD2|MOD1|RSV|
+ * ----------------------------------------
+ * 31 5 4 3 2 1 0
+ *
+ * SBUS: Enable MBus Arbiter on the SBus 0=off 1=on
+ * MOD3: Enable MBus Arbiter on MBus module 3 0=off 1=on
+ * MOD2: Enable MBus Arbiter on MBus module 2 0=off 1=on
+ * MOD1: Enable MBus Arbiter on MBus module 1 0=off 1=on
+ */
+
+#define ECC_MBAE_SBUS 0x00000010
+#define ECC_MBAE_MOD3 0x00000008
+#define ECC_MBAE_MOD2 0x00000004
+#define ECC_MBAE_MOD1 0x00000002
+
+/* ECC Fault Control Register layout:
+ *
+ * -----------------------------
+ * | RESV | ECHECK | EINT |
+ * -----------------------------
+ * 31 2 1 0
+ *
+ * ECHECK: Enable ECC checking. 0=off 1=on
+ * EINT: Enable Interrupts for correctable errors. 0=off 1=on
+ */
+#define ECC_FCR_CHECK 0x00000002
+#define ECC_FCR_INTENAB 0x00000001
+
+/* ECC Fault Address Register Zero layout:
+ *
+ * -----------------------------------------------------
+ * | MID | S | RSV | VA | BM |AT| C| SZ |TYP| PADDR |
+ * -----------------------------------------------------
+ * 31-28 27 26-22 21-14 13 12 11 10-8 7-4 3-0
+ *
+ * MID: ModuleID of the faulting processor. ie. who did it?
+ * S: Supervisor/Privileged access? 0=no 1=yes
+ * VA: Bits 19-12 of the virtual faulting address, these are the
+ * superset bits in the virtual cache and can be used for
+ * a flush operation if necessary.
+ * BM: Boot mode? 0=no 1=yes This is just like the SRMMU boot
+ * mode bit.
+ * AT: Did this fault happen during an atomic instruction? 0=no
+ * 1=yes. This means either an 'ldstub' or 'swap' instruction
+ * was in progress (but not finished) when this fault happened.
+ * This indicated whether the bus was locked when the fault
+ * occurred.
+ * C: Did the pte for this access indicate that it was cacheable?
+ * 0=no 1=yes
+ * SZ: The size of the transaction.
+ * TYP: The transaction type.
+ * PADDR: Bits 35-32 of the physical address for the fault.
+ */
+#define ECC_FADDR0_MIDMASK 0xf0000000
+#define ECC_FADDR0_S 0x08000000
+#define ECC_FADDR0_VADDR 0x003fc000
+#define ECC_FADDR0_BMODE 0x00002000
+#define ECC_FADDR0_ATOMIC 0x00001000
+#define ECC_FADDR0_CACHE 0x00000800
+#define ECC_FADDR0_SIZE 0x00000700
+#define ECC_FADDR0_TYPE 0x000000f0
+#define ECC_FADDR0_PADDR 0x0000000f
+
+/* ECC Fault Address Register One layout:
+ *
+ * -------------------------------------
+ * | Physical Address 31-0 |
+ * -------------------------------------
+ * 31 0
+ *
+ * You get the upper 4 bits of the physical address from the
+ * PADDR field in ECC Fault Address Zero register.
+ */
+
+/* ECC Fault Status Register layout:
+ *
+ * ----------------------------------------------
+ * | RESV|C2E|MULT|SYNDROME|DWORD|UNC|TIMEO|BS|C|
+ * ----------------------------------------------
+ * 31-18 17 16 15-8 7-4 3 2 1 0
+ *
+ * C2E: A C2 graphics error occurred. 0=no 1=yes (SS10 only)
+ * MULT: Multiple errors occurred ;-O 0=no 1=prom_panic(yes)
+ * SYNDROME: Controller is mentally unstable.
+ * DWORD:
+ * UNC: Uncorrectable error. 0=no 1=yes
+ * TIMEO: Timeout occurred. 0=no 1=yes
+ * BS: C2 graphics bad slot access. 0=no 1=yes (SS10 only)
+ * C: Correctable error? 0=no 1=yes
+ */
+
+#define ECC_FSR_C2ERR 0x00020000
+#define ECC_FSR_MULT 0x00010000
+#define ECC_FSR_SYND 0x0000ff00
+#define ECC_FSR_DWORD 0x000000f0
+#define ECC_FSR_UNC 0x00000008
+#define ECC_FSR_TIMEO 0x00000004
+#define ECC_FSR_BADSLOT 0x00000002
+#define ECC_FSR_C 0x00000001
+
+#endif /* !(_SPARC_ECC_H) */
diff --git a/arch/sparc/include/asm/eeprom.h b/arch/sparc/include/asm/eeprom.h
new file mode 100644
index 00000000000..e17beeceb40
--- /dev/null
+++ b/arch/sparc/include/asm/eeprom.h
@@ -0,0 +1,9 @@
+/*
+ * eeprom.h: Definitions for the Sun eeprom.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+/* The EEPROM and the Mostek Mk48t02 use the same IO address space
+ * for their registers/data areas. The IDPROM lives here too.
+ */
diff --git a/arch/sparc/include/asm/elf.h b/arch/sparc/include/asm/elf.h
new file mode 100644
index 00000000000..0a2816c50b0
--- /dev/null
+++ b/arch/sparc/include/asm/elf.h
@@ -0,0 +1,8 @@
+#ifndef ___ASM_SPARC_ELF_H
+#define ___ASM_SPARC_ELF_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/elf_64.h>
+#else
+#include <asm/elf_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/elf_32.h b/arch/sparc/include/asm/elf_32.h
new file mode 100644
index 00000000000..a24e41fcdde
--- /dev/null
+++ b/arch/sparc/include/asm/elf_32.h
@@ -0,0 +1,131 @@
+#ifndef __ASMSPARC_ELF_H
+#define __ASMSPARC_ELF_H
+
+/*
+ * ELF register definitions..
+ */
+
+#include <asm/ptrace.h>
+
+/*
+ * Sparc section types
+ */
+#define STT_REGISTER 13
+
+/*
+ * Sparc ELF relocation types
+ */
+#define R_SPARC_NONE 0
+#define R_SPARC_8 1
+#define R_SPARC_16 2
+#define R_SPARC_32 3
+#define R_SPARC_DISP8 4
+#define R_SPARC_DISP16 5
+#define R_SPARC_DISP32 6
+#define R_SPARC_WDISP30 7
+#define R_SPARC_WDISP22 8
+#define R_SPARC_HI22 9
+#define R_SPARC_22 10
+#define R_SPARC_13 11
+#define R_SPARC_LO10 12
+#define R_SPARC_GOT10 13
+#define R_SPARC_GOT13 14
+#define R_SPARC_GOT22 15
+#define R_SPARC_PC10 16
+#define R_SPARC_PC22 17
+#define R_SPARC_WPLT30 18
+#define R_SPARC_COPY 19
+#define R_SPARC_GLOB_DAT 20
+#define R_SPARC_JMP_SLOT 21
+#define R_SPARC_RELATIVE 22
+#define R_SPARC_UA32 23
+#define R_SPARC_PLT32 24
+#define R_SPARC_HIPLT22 25
+#define R_SPARC_LOPLT10 26
+#define R_SPARC_PCPLT32 27
+#define R_SPARC_PCPLT22 28
+#define R_SPARC_PCPLT10 29
+#define R_SPARC_10 30
+#define R_SPARC_11 31
+#define R_SPARC_64 32
+#define R_SPARC_OLO10 33
+#define R_SPARC_WDISP16 40
+#define R_SPARC_WDISP19 41
+#define R_SPARC_7 43
+#define R_SPARC_5 44
+#define R_SPARC_6 45
+
+/* Bits present in AT_HWCAP, primarily for Sparc32. */
+
+#define HWCAP_SPARC_FLUSH 1 /* CPU supports flush instruction. */
+#define HWCAP_SPARC_STBAR 2
+#define HWCAP_SPARC_SWAP 4
+#define HWCAP_SPARC_MULDIV 8
+#define HWCAP_SPARC_V9 16
+#define HWCAP_SPARC_ULTRA3 32
+
+#define CORE_DUMP_USE_REGSET
+
+/* Format is:
+ * G0 --> G7
+ * O0 --> O7
+ * L0 --> L7
+ * I0 --> I7
+ * PSR, PC, nPC, Y, WIM, TBR
+ */
+typedef unsigned long elf_greg_t;
+#define ELF_NGREG 38
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+typedef struct {
+ union {
+ unsigned long pr_regs[32];
+ double pr_dregs[16];
+ } pr_fr;
+ unsigned long __unused;
+ unsigned long pr_fsr;
+ unsigned char pr_qcnt;
+ unsigned char pr_q_entrysize;
+ unsigned char pr_en;
+ unsigned int pr_q[64];
+} elf_fpregset_t;
+
+#include <asm/mbus.h>
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x) ((x)->e_machine == EM_SPARC)
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_ARCH EM_SPARC
+#define ELF_CLASS ELFCLASS32
+#define ELF_DATA ELFDATA2MSB
+
+#define ELF_EXEC_PAGESIZE 4096
+
+
+/* This is the location that an ET_DYN program is loaded if exec'ed. Typical
+ use of this is to invoke "./ld.so someprog" to test out a new version of
+ the loader. We need to make sure that it is out of the way of the program
+ that it will "exec", and that there is sufficient room for the brk. */
+
+#define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE)
+
+/* This yields a mask that user programs can use to figure out what
+ instruction set this cpu supports. This can NOT be done in userspace
+ on Sparc. */
+
+/* Most sun4m's have them all. */
+#define ELF_HWCAP (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | \
+ HWCAP_SPARC_SWAP | HWCAP_SPARC_MULDIV)
+
+/* This yields a string that ld.so will use to load implementation
+ specific libraries for optimization. This is more specific in
+ intent than poking at uname or /proc/cpuinfo. */
+
+#define ELF_PLATFORM (NULL)
+
+#endif /* !(__ASMSPARC_ELF_H) */
diff --git a/arch/sparc/include/asm/elf_64.h b/arch/sparc/include/asm/elf_64.h
new file mode 100644
index 00000000000..370ca1e71ff
--- /dev/null
+++ b/arch/sparc/include/asm/elf_64.h
@@ -0,0 +1,212 @@
+#ifndef __ASM_SPARC64_ELF_H
+#define __ASM_SPARC64_ELF_H
+
+/*
+ * ELF register definitions..
+ */
+
+#include <asm/ptrace.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/spitfire.h>
+
+/*
+ * Sparc section types
+ */
+#define STT_REGISTER 13
+
+/*
+ * Sparc ELF relocation types
+ */
+#define R_SPARC_NONE 0
+#define R_SPARC_8 1
+#define R_SPARC_16 2
+#define R_SPARC_32 3
+#define R_SPARC_DISP8 4
+#define R_SPARC_DISP16 5
+#define R_SPARC_DISP32 6
+#define R_SPARC_WDISP30 7
+#define R_SPARC_WDISP22 8
+#define R_SPARC_HI22 9
+#define R_SPARC_22 10
+#define R_SPARC_13 11
+#define R_SPARC_LO10 12
+#define R_SPARC_GOT10 13
+#define R_SPARC_GOT13 14
+#define R_SPARC_GOT22 15
+#define R_SPARC_PC10 16
+#define R_SPARC_PC22 17
+#define R_SPARC_WPLT30 18
+#define R_SPARC_COPY 19
+#define R_SPARC_GLOB_DAT 20
+#define R_SPARC_JMP_SLOT 21
+#define R_SPARC_RELATIVE 22
+#define R_SPARC_UA32 23
+#define R_SPARC_PLT32 24
+#define R_SPARC_HIPLT22 25
+#define R_SPARC_LOPLT10 26
+#define R_SPARC_PCPLT32 27
+#define R_SPARC_PCPLT22 28
+#define R_SPARC_PCPLT10 29
+#define R_SPARC_10 30
+#define R_SPARC_11 31
+#define R_SPARC_64 32
+#define R_SPARC_OLO10 33
+#define R_SPARC_WDISP16 40
+#define R_SPARC_WDISP19 41
+#define R_SPARC_7 43
+#define R_SPARC_5 44
+#define R_SPARC_6 45
+
+/* Bits present in AT_HWCAP, primarily for Sparc32. */
+#define HWCAP_SPARC_FLUSH 0x00000001
+#define HWCAP_SPARC_STBAR 0x00000002
+#define HWCAP_SPARC_SWAP 0x00000004
+#define HWCAP_SPARC_MULDIV 0x00000008
+#define HWCAP_SPARC_V9 0x00000010
+#define HWCAP_SPARC_ULTRA3 0x00000020
+#define HWCAP_SPARC_BLKINIT 0x00000040
+#define HWCAP_SPARC_N2 0x00000080
+
+/* Solaris compatible AT_HWCAP bits. */
+#define AV_SPARC_MUL32 0x00000100 /* 32x32 multiply is efficient */
+#define AV_SPARC_DIV32 0x00000200 /* 32x32 divide is efficient */
+#define AV_SPARC_FSMULD 0x00000400 /* 'fsmuld' is efficient */
+#define AV_SPARC_V8PLUS 0x00000800 /* v9 insn available to 32bit */
+#define AV_SPARC_POPC 0x00001000 /* 'popc' is efficient */
+#define AV_SPARC_VIS 0x00002000 /* VIS insns available */
+#define AV_SPARC_VIS2 0x00004000 /* VIS2 insns available */
+#define AV_SPARC_ASI_BLK_INIT 0x00008000 /* block init ASIs available */
+#define AV_SPARC_FMAF 0x00010000 /* fused multiply-add */
+#define AV_SPARC_VIS3 0x00020000 /* VIS3 insns available */
+#define AV_SPARC_HPC 0x00040000 /* HPC insns available */
+#define AV_SPARC_RANDOM 0x00080000 /* 'random' insn available */
+#define AV_SPARC_TRANS 0x00100000 /* transaction insns available */
+#define AV_SPARC_FJFMAU 0x00200000 /* unfused multiply-add */
+#define AV_SPARC_IMA 0x00400000 /* integer multiply-add */
+#define AV_SPARC_ASI_CACHE_SPARING \
+ 0x00800000 /* cache sparing ASIs available */
+#define AV_SPARC_PAUSE 0x01000000 /* PAUSE available */
+#define AV_SPARC_CBCOND 0x02000000 /* CBCOND insns available */
+
+/* Solaris decided to enumerate every single crypto instruction type
+ * in the AT_HWCAP bits. This is wasteful, since if crypto is present,
+ * you still need to look in the CFR register to see if the opcode is
+ * really available. So we simply advertise only "crypto" support.
+ */
+#define HWCAP_SPARC_CRYPTO 0x04000000 /* CRYPTO insns available */
+
+#define CORE_DUMP_USE_REGSET
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_ARCH EM_SPARCV9
+#define ELF_CLASS ELFCLASS64
+#define ELF_DATA ELFDATA2MSB
+
+/* Format of 64-bit elf_gregset_t is:
+ * G0 --> G7
+ * O0 --> O7
+ * L0 --> L7
+ * I0 --> I7
+ * TSTATE
+ * TPC
+ * TNPC
+ * Y
+ */
+typedef unsigned long elf_greg_t;
+#define ELF_NGREG 36
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+typedef struct {
+ unsigned long pr_regs[32];
+ unsigned long pr_fsr;
+ unsigned long pr_gsr;
+ unsigned long pr_fprs;
+} elf_fpregset_t;
+
+/* Format of 32-bit elf_gregset_t is:
+ * G0 --> G7
+ * O0 --> O7
+ * L0 --> L7
+ * I0 --> I7
+ * PSR, PC, nPC, Y, WIM, TBR
+ */
+typedef unsigned int compat_elf_greg_t;
+#define COMPAT_ELF_NGREG 38
+typedef compat_elf_greg_t compat_elf_gregset_t[COMPAT_ELF_NGREG];
+
+typedef struct {
+ union {
+ unsigned int pr_regs[32];
+ unsigned long pr_dregs[16];
+ } pr_fr;
+ unsigned int __unused;
+ unsigned int pr_fsr;
+ unsigned char pr_qcnt;
+ unsigned char pr_q_entrysize;
+ unsigned char pr_en;
+ unsigned int pr_q[64];
+} compat_elf_fpregset_t;
+
+/* UltraSparc extensions. Still unused, but will be eventually. */
+typedef struct {
+ unsigned int pr_type;
+ unsigned int pr_align;
+ union {
+ struct {
+ union {
+ unsigned int pr_regs[32];
+ unsigned long pr_dregs[16];
+ long double pr_qregs[8];
+ } pr_xfr;
+ } pr_v8p;
+ unsigned int pr_xfsr;
+ unsigned int pr_fprs;
+ unsigned int pr_xg[8];
+ unsigned int pr_xo[8];
+ unsigned long pr_tstate;
+ unsigned int pr_filler[8];
+ } pr_un;
+} elf_xregset_t;
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x) ((x)->e_machine == ELF_ARCH)
+#define compat_elf_check_arch(x) ((x)->e_machine == EM_SPARC || \
+ (x)->e_machine == EM_SPARC32PLUS)
+#define compat_start_thread start_thread32
+
+#define ELF_EXEC_PAGESIZE PAGE_SIZE
+
+/* This is the location that an ET_DYN program is loaded if exec'ed. Typical
+ use of this is to invoke "./ld.so someprog" to test out a new version of
+ the loader. We need to make sure that it is out of the way of the program
+ that it will "exec", and that there is sufficient room for the brk. */
+
+#define ELF_ET_DYN_BASE 0x0000010000000000UL
+#define COMPAT_ELF_ET_DYN_BASE 0x0000000070000000UL
+
+extern unsigned long sparc64_elf_hwcap;
+#define ELF_HWCAP sparc64_elf_hwcap
+
+/* This yields a string that ld.so will use to load implementation
+ specific libraries for optimization. This is more specific in
+ intent than poking at uname or /proc/cpuinfo. */
+
+#define ELF_PLATFORM (NULL)
+
+#define SET_PERSONALITY(ex) \
+do { if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \
+ set_thread_flag(TIF_32BIT); \
+ else \
+ clear_thread_flag(TIF_32BIT); \
+ /* flush_thread will update pgd cache */ \
+ if (personality(current->personality) != PER_LINUX32) \
+ set_personality(PER_LINUX | \
+ (current->personality & (~PER_MASK))); \
+} while (0)
+
+#endif /* !(__ASM_SPARC64_ELF_H) */
diff --git a/arch/sparc/include/asm/estate.h b/arch/sparc/include/asm/estate.h
new file mode 100644
index 00000000000..520c08560d1
--- /dev/null
+++ b/arch/sparc/include/asm/estate.h
@@ -0,0 +1,49 @@
+#ifndef _SPARC64_ESTATE_H
+#define _SPARC64_ESTATE_H
+
+/* UltraSPARC-III E-cache Error Enable */
+#define ESTATE_ERROR_FMT 0x0000000000040000 /* Force MTAG ECC */
+#define ESTATE_ERROR_FMESS 0x000000000003c000 /* Forced MTAG ECC val */
+#define ESTATE_ERROR_FMD 0x0000000000002000 /* Force DATA ECC */
+#define ESTATE_ERROR_FDECC 0x0000000000001ff0 /* Forced DATA ECC val */
+#define ESTATE_ERROR_UCEEN 0x0000000000000008 /* See below */
+#define ESTATE_ERROR_NCEEN 0x0000000000000002 /* See below */
+#define ESTATE_ERROR_CEEN 0x0000000000000001 /* See below */
+
+/* UCEEN enables the fast_ECC_error trap for: 1) software correctable E-cache
+ * errors 2) uncorrectable E-cache errors. Such events only occur on reads
+ * of the E-cache by the local processor for: 1) data loads 2) instruction
+ * fetches 3) atomic operations. Such events _cannot_ occur for: 1) merge
+ * 2) writeback 2) copyout. The AFSR bits associated with these traps are
+ * UCC and UCU.
+ */
+
+/* NCEEN enables instruction_access_error, data_access_error, and ECC_error traps
+ * for uncorrectable ECC errors and system errors.
+ *
+ * Uncorrectable system bus data error or MTAG ECC error, system bus TimeOUT,
+ * or system bus BusERR:
+ * 1) As the result of an instruction fetch, will generate instruction_access_error
+ * 2) As the result of a load etc. will generate data_access_error.
+ * 3) As the result of store merge completion, writeback, or copyout will
+ * generate a disrupting ECC_error trap.
+ * 4) As the result of such errors on instruction vector fetch can generate any
+ * of the 3 trap types.
+ *
+ * The AFSR bits associated with these traps are EMU, EDU, WDU, CPU, IVU, UE,
+ * BERR, and TO.
+ */
+
+/* CEEN enables the ECC_error trap for hardware corrected ECC errors. System bus
+ * reads resulting in a hardware corrected data or MTAG ECC error will generate an
+ * ECC_error disrupting trap with this bit enabled.
+ *
+ * This same trap will also be generated when a hardware corrected ECC error results
+ * during store merge, writeback, and copyout operations.
+ */
+
+/* In general, if the trap enable bits above are disabled the AFSR bits will still
+ * log the events even though the trap will not be generated by the processor.
+ */
+
+#endif /* _SPARC64_ESTATE_H */
diff --git a/arch/sparc/include/asm/fb.h b/arch/sparc/include/asm/fb.h
new file mode 100644
index 00000000000..2173432ad7f
--- /dev/null
+++ b/arch/sparc/include/asm/fb.h
@@ -0,0 +1,33 @@
+#ifndef _SPARC_FB_H_
+#define _SPARC_FB_H_
+#include <linux/console.h>
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+#include <asm/prom.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+ unsigned long off)
+{
+#ifdef CONFIG_SPARC64
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+#endif
+}
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+ struct device *dev = info->device;
+ struct device_node *node;
+
+ if (console_set_on_cmdline)
+ return 0;
+
+ node = dev->of_node;
+ if (node &&
+ node == of_console_device)
+ return 1;
+
+ return 0;
+}
+
+#endif /* _SPARC_FB_H_ */
diff --git a/arch/sparc/include/asm/fbio.h b/arch/sparc/include/asm/fbio.h
new file mode 100644
index 00000000000..1d9afe277e9
--- /dev/null
+++ b/arch/sparc/include/asm/fbio.h
@@ -0,0 +1,72 @@
+#ifndef __LINUX_FBIO_H
+#define __LINUX_FBIO_H
+
+#include <uapi/asm/fbio.h>
+
+#define FBIOPUTCMAP_SPARC _IOW('F', 3, struct fbcmap)
+#define FBIOGETCMAP_SPARC _IOW('F', 4, struct fbcmap)
+/* Addresses on the fd of a cgsix that are mappable */
+#define CG6_FBC 0x70000000
+#define CG6_TEC 0x70001000
+#define CG6_BTREGS 0x70002000
+#define CG6_FHC 0x70004000
+#define CG6_THC 0x70005000
+#define CG6_ROM 0x70006000
+#define CG6_RAM 0x70016000
+#define CG6_DHC 0x80000000
+
+#define CG3_MMAP_OFFSET 0x4000000
+
+/* Addresses on the fd of a tcx that are mappable */
+#define TCX_RAM8BIT 0x00000000
+#define TCX_RAM24BIT 0x01000000
+#define TCX_UNK3 0x10000000
+#define TCX_UNK4 0x20000000
+#define TCX_CONTROLPLANE 0x28000000
+#define TCX_UNK6 0x30000000
+#define TCX_UNK7 0x38000000
+#define TCX_TEC 0x70000000
+#define TCX_BTREGS 0x70002000
+#define TCX_THC 0x70004000
+#define TCX_DHC 0x70008000
+#define TCX_ALT 0x7000a000
+#define TCX_SYNC 0x7000e000
+#define TCX_UNK2 0x70010000
+
+/* CG14 definitions */
+
+/* Offsets into the OBIO space: */
+#define CG14_REGS 0 /* registers */
+#define CG14_CURSORREGS 0x1000 /* cursor registers */
+#define CG14_DACREGS 0x2000 /* DAC registers */
+#define CG14_XLUT 0x3000 /* X Look Up Table -- ??? */
+#define CG14_CLUT1 0x4000 /* Color Look Up Table */
+#define CG14_CLUT2 0x5000 /* Color Look Up Table */
+#define CG14_CLUT3 0x6000 /* Color Look Up Table */
+#define CG14_AUTO 0xf000
+
+struct fbcmap32 {
+ int index; /* first element (0 origin) */
+ int count;
+ u32 red;
+ u32 green;
+ u32 blue;
+};
+
+#define FBIOPUTCMAP32 _IOW('F', 3, struct fbcmap32)
+#define FBIOGETCMAP32 _IOW('F', 4, struct fbcmap32)
+
+struct fbcursor32 {
+ short set; /* what to set, choose from the list above */
+ short enable; /* cursor on/off */
+ struct fbcurpos pos; /* cursor position */
+ struct fbcurpos hot; /* cursor hot spot */
+ struct fbcmap32 cmap; /* color map info */
+ struct fbcurpos size; /* cursor bit map size */
+ u32 image; /* cursor image bits */
+ u32 mask; /* cursor mask bits */
+};
+
+#define FBIOSCURSOR32 _IOW('F', 24, struct fbcursor32)
+#define FBIOGCURSOR32 _IOW('F', 25, struct fbcursor32)
+#endif /* __LINUX_FBIO_H */
diff --git a/arch/sparc/include/asm/fhc.h b/arch/sparc/include/asm/fhc.h
new file mode 100644
index 00000000000..57f1b303ad5
--- /dev/null
+++ b/arch/sparc/include/asm/fhc.h
@@ -0,0 +1,80 @@
+/* fhc.h: FHC and Clock board register definitions.
+ *
+ * Copyright (C) 1997, 1999 David S. Miller (davem@redhat.com)
+ */
+
+#ifndef _SPARC64_FHC_H
+#define _SPARC64_FHC_H
+
+/* Clock board register offsets. */
+#define CLOCK_CTRL 0x00UL /* Main control */
+#define CLOCK_STAT1 0x10UL /* Status one */
+#define CLOCK_STAT2 0x20UL /* Status two */
+#define CLOCK_PWRSTAT 0x30UL /* Power status */
+#define CLOCK_PWRPRES 0x40UL /* Power presence */
+#define CLOCK_TEMP 0x50UL /* Temperature */
+#define CLOCK_IRQDIAG 0x60UL /* IRQ diagnostics */
+#define CLOCK_PWRSTAT2 0x70UL /* Power status two */
+
+#define CLOCK_CTRL_LLED 0x04 /* Left LED, 0 == on */
+#define CLOCK_CTRL_MLED 0x02 /* Mid LED, 1 == on */
+#define CLOCK_CTRL_RLED 0x01 /* RIght LED, 1 == on */
+
+/* Firehose controller register offsets */
+#define FHC_PREGS_ID 0x00UL /* FHC ID */
+#define FHC_ID_VERS 0xf0000000 /* Version of this FHC */
+#define FHC_ID_PARTID 0x0ffff000 /* Part ID code (0x0f9f == FHC) */
+#define FHC_ID_MANUF 0x0000007e /* Manufacturer (0x3e == SUN's JEDEC)*/
+#define FHC_ID_RESV 0x00000001 /* Read as one */
+#define FHC_PREGS_RCS 0x10UL /* FHC Reset Control/Status Register */
+#define FHC_RCS_POR 0x80000000 /* Last reset was a power cycle */
+#define FHC_RCS_SPOR 0x40000000 /* Last reset was sw power on reset */
+#define FHC_RCS_SXIR 0x20000000 /* Last reset was sw XIR reset */
+#define FHC_RCS_BPOR 0x10000000 /* Last reset was due to POR button */
+#define FHC_RCS_BXIR 0x08000000 /* Last reset was due to XIR button */
+#define FHC_RCS_WEVENT 0x04000000 /* CPU reset was due to wakeup event */
+#define FHC_RCS_CFATAL 0x02000000 /* Centerplane Fatal Error signalled */
+#define FHC_RCS_FENAB 0x01000000 /* Fatal errors elicit system reset */
+#define FHC_PREGS_CTRL 0x20UL /* FHC Control Register */
+#define FHC_CONTROL_ICS 0x00100000 /* Ignore Centerplane Signals */
+#define FHC_CONTROL_FRST 0x00080000 /* Fatal Error Reset Enable */
+#define FHC_CONTROL_LFAT 0x00040000 /* AC/DC signalled a local error */
+#define FHC_CONTROL_SLINE 0x00010000 /* Firmware Synchronization Line */
+#define FHC_CONTROL_DCD 0x00008000 /* DC-->DC Converter Disable */
+#define FHC_CONTROL_POFF 0x00004000 /* AC/DC Controller PLL Disable */
+#define FHC_CONTROL_FOFF 0x00002000 /* FHC Controller PLL Disable */
+#define FHC_CONTROL_AOFF 0x00001000 /* CPU A SRAM/SBD Low Power Mode */
+#define FHC_CONTROL_BOFF 0x00000800 /* CPU B SRAM/SBD Low Power Mode */
+#define FHC_CONTROL_PSOFF 0x00000400 /* Turns off this FHC's power supply */
+#define FHC_CONTROL_IXIST 0x00000200 /* 0=FHC tells clock board it exists */
+#define FHC_CONTROL_XMSTR 0x00000100 /* 1=Causes this FHC to be XIR master*/
+#define FHC_CONTROL_LLED 0x00000040 /* 0=Left LED ON */
+#define FHC_CONTROL_MLED 0x00000020 /* 1=Middle LED ON */
+#define FHC_CONTROL_RLED 0x00000010 /* 1=Right LED */
+#define FHC_CONTROL_BPINS 0x00000003 /* Spare Bidirectional Pins */
+#define FHC_PREGS_BSR 0x30UL /* FHC Board Status Register */
+#define FHC_BSR_DA64 0x00040000 /* Port A: 0=128bit 1=64bit data path */
+#define FHC_BSR_DB64 0x00020000 /* Port B: 0=128bit 1=64bit data path */
+#define FHC_BSR_BID 0x0001e000 /* Board ID */
+#define FHC_BSR_SA 0x00001c00 /* Port A UPA Speed (from the pins) */
+#define FHC_BSR_SB 0x00000380 /* Port B UPA Speed (from the pins) */
+#define FHC_BSR_NDIAG 0x00000040 /* Not in Diag Mode */
+#define FHC_BSR_NTBED 0x00000020 /* Not in TestBED Mode */
+#define FHC_BSR_NIA 0x0000001c /* Jumper, bit 18 in PROM space */
+#define FHC_BSR_SI 0x00000001 /* Spare input pin value */
+#define FHC_PREGS_ECC 0x40UL /* FHC ECC Control Register (16 bits) */
+#define FHC_PREGS_JCTRL 0xf0UL /* FHC JTAG Control Register */
+#define FHC_JTAG_CTRL_MENAB 0x80000000 /* Indicates this is JTAG Master */
+#define FHC_JTAG_CTRL_MNONE 0x40000000 /* Indicates no JTAG Master present */
+#define FHC_PREGS_JCMD 0x100UL /* FHC JTAG Command Register */
+#define FHC_IREG_IGN 0x00UL /* This FHC's IGN */
+#define FHC_FFREGS_IMAP 0x00UL /* FHC Fanfail IMAP */
+#define FHC_FFREGS_ICLR 0x10UL /* FHC Fanfail ICLR */
+#define FHC_SREGS_IMAP 0x00UL /* FHC System IMAP */
+#define FHC_SREGS_ICLR 0x10UL /* FHC System ICLR */
+#define FHC_UREGS_IMAP 0x00UL /* FHC Uart IMAP */
+#define FHC_UREGS_ICLR 0x10UL /* FHC Uart ICLR */
+#define FHC_TREGS_IMAP 0x00UL /* FHC TOD IMAP */
+#define FHC_TREGS_ICLR 0x10UL /* FHC TOD ICLR */
+
+#endif /* !(_SPARC64_FHC_H) */
diff --git a/arch/sparc/include/asm/floppy.h b/arch/sparc/include/asm/floppy.h
new file mode 100644
index 00000000000..faebd335b60
--- /dev/null
+++ b/arch/sparc/include/asm/floppy.h
@@ -0,0 +1,8 @@
+#ifndef ___ASM_SPARC_FLOPPY_H
+#define ___ASM_SPARC_FLOPPY_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/floppy_64.h>
+#else
+#include <asm/floppy_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/floppy_32.h b/arch/sparc/include/asm/floppy_32.h
new file mode 100644
index 00000000000..071b83e52f1
--- /dev/null
+++ b/arch/sparc/include/asm/floppy_32.h
@@ -0,0 +1,393 @@
+/* asm/floppy.h: Sparc specific parts of the Floppy driver.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@davemloft.net)
+ */
+
+#ifndef __ASM_SPARC_FLOPPY_H
+#define __ASM_SPARC_FLOPPY_H
+
+#include <linux/of.h>
+#include <linux/of_device.h>
+
+#include <asm/pgtable.h>
+#include <asm/idprom.h>
+#include <asm/oplib.h>
+#include <asm/auxio.h>
+#include <asm/setup.h>
+#include <asm/page.h>
+#include <asm/irq.h>
+
+/* We don't need no stinkin' I/O port allocation crap. */
+#undef release_region
+#undef request_region
+#define release_region(X, Y) do { } while(0)
+#define request_region(X, Y, Z) (1)
+
+/* References:
+ * 1) Netbsd Sun floppy driver.
+ * 2) NCR 82077 controller manual
+ * 3) Intel 82077 controller manual
+ */
+struct sun_flpy_controller {
+ volatile unsigned char status_82072; /* Main Status reg. */
+#define dcr_82072 status_82072 /* Digital Control reg. */
+#define status1_82077 status_82072 /* Auxiliary Status reg. 1 */
+
+ volatile unsigned char data_82072; /* Data fifo. */
+#define status2_82077 data_82072 /* Auxiliary Status reg. 2 */
+
+ volatile unsigned char dor_82077; /* Digital Output reg. */
+ volatile unsigned char tapectl_82077; /* What the? Tape control reg? */
+
+ volatile unsigned char status_82077; /* Main Status Register. */
+#define drs_82077 status_82077 /* Digital Rate Select reg. */
+
+ volatile unsigned char data_82077; /* Data fifo. */
+ volatile unsigned char ___unused;
+ volatile unsigned char dir_82077; /* Digital Input reg. */
+#define dcr_82077 dir_82077 /* Config Control reg. */
+};
+
+/* You'll only ever find one controller on a SparcStation anyways. */
+static struct sun_flpy_controller *sun_fdc = NULL;
+
+struct sun_floppy_ops {
+ unsigned char (*fd_inb)(int port);
+ void (*fd_outb)(unsigned char value, int port);
+};
+
+static struct sun_floppy_ops sun_fdops;
+
+#define fd_inb(port) sun_fdops.fd_inb(port)
+#define fd_outb(value,port) sun_fdops.fd_outb(value,port)
+#define fd_enable_dma() sun_fd_enable_dma()
+#define fd_disable_dma() sun_fd_disable_dma()
+#define fd_request_dma() (0) /* nothing... */
+#define fd_free_dma() /* nothing... */
+#define fd_clear_dma_ff() /* nothing... */
+#define fd_set_dma_mode(mode) sun_fd_set_dma_mode(mode)
+#define fd_set_dma_addr(addr) sun_fd_set_dma_addr(addr)
+#define fd_set_dma_count(count) sun_fd_set_dma_count(count)
+#define fd_enable_irq() /* nothing... */
+#define fd_disable_irq() /* nothing... */
+#define fd_cacheflush(addr, size) /* nothing... */
+#define fd_request_irq() sun_fd_request_irq()
+#define fd_free_irq() /* nothing... */
+#if 0 /* P3: added by Alain, these cause a MMU corruption. 19960524 XXX */
+#define fd_dma_mem_alloc(size) ((unsigned long) vmalloc(size))
+#define fd_dma_mem_free(addr,size) (vfree((void *)(addr)))
+#endif
+
+/* XXX This isn't really correct. XXX */
+#define get_dma_residue(x) (0)
+
+#define FLOPPY0_TYPE 4
+#define FLOPPY1_TYPE 0
+
+/* Super paranoid... */
+#undef HAVE_DISABLE_HLT
+
+/* Here is where we catch the floppy driver trying to initialize,
+ * therefore this is where we call the PROM device tree probing
+ * routine etc. on the Sparc.
+ */
+#define FDC1 sun_floppy_init()
+
+#define N_FDC 1
+#define N_DRIVE 8
+
+/* No 64k boundary crossing problems on the Sparc. */
+#define CROSS_64KB(a,s) (0)
+
+/* Routines unique to each controller type on a Sun. */
+static void sun_set_dor(unsigned char value, int fdc_82077)
+{
+ if (fdc_82077)
+ sun_fdc->dor_82077 = value;
+}
+
+static unsigned char sun_read_dir(void)
+{
+ return sun_fdc->dir_82077;
+}
+
+static unsigned char sun_82072_fd_inb(int port)
+{
+ udelay(5);
+ switch(port & 7) {
+ default:
+ printk("floppy: Asked to read unknown port %d\n", port);
+ panic("floppy: Port bolixed.");
+ case 4: /* FD_STATUS */
+ return sun_fdc->status_82072 & ~STATUS_DMA;
+ case 5: /* FD_DATA */
+ return sun_fdc->data_82072;
+ case 7: /* FD_DIR */
+ return sun_read_dir();
+ }
+ panic("sun_82072_fd_inb: How did I get here?");
+}
+
+static void sun_82072_fd_outb(unsigned char value, int port)
+{
+ udelay(5);
+ switch(port & 7) {
+ default:
+ printk("floppy: Asked to write to unknown port %d\n", port);
+ panic("floppy: Port bolixed.");
+ case 2: /* FD_DOR */
+ sun_set_dor(value, 0);
+ break;
+ case 5: /* FD_DATA */
+ sun_fdc->data_82072 = value;
+ break;
+ case 7: /* FD_DCR */
+ sun_fdc->dcr_82072 = value;
+ break;
+ case 4: /* FD_STATUS */
+ sun_fdc->status_82072 = value;
+ break;
+ }
+ return;
+}
+
+static unsigned char sun_82077_fd_inb(int port)
+{
+ udelay(5);
+ switch(port & 7) {
+ default:
+ printk("floppy: Asked to read unknown port %d\n", port);
+ panic("floppy: Port bolixed.");
+ case 0: /* FD_STATUS_0 */
+ return sun_fdc->status1_82077;
+ case 1: /* FD_STATUS_1 */
+ return sun_fdc->status2_82077;
+ case 2: /* FD_DOR */
+ return sun_fdc->dor_82077;
+ case 3: /* FD_TDR */
+ return sun_fdc->tapectl_82077;
+ case 4: /* FD_STATUS */
+ return sun_fdc->status_82077 & ~STATUS_DMA;
+ case 5: /* FD_DATA */
+ return sun_fdc->data_82077;
+ case 7: /* FD_DIR */
+ return sun_read_dir();
+ }
+ panic("sun_82077_fd_inb: How did I get here?");
+}
+
+static void sun_82077_fd_outb(unsigned char value, int port)
+{
+ udelay(5);
+ switch(port & 7) {
+ default:
+ printk("floppy: Asked to write to unknown port %d\n", port);
+ panic("floppy: Port bolixed.");
+ case 2: /* FD_DOR */
+ sun_set_dor(value, 1);
+ break;
+ case 5: /* FD_DATA */
+ sun_fdc->data_82077 = value;
+ break;
+ case 7: /* FD_DCR */
+ sun_fdc->dcr_82077 = value;
+ break;
+ case 4: /* FD_STATUS */
+ sun_fdc->status_82077 = value;
+ break;
+ case 3: /* FD_TDR */
+ sun_fdc->tapectl_82077 = value;
+ break;
+ }
+ return;
+}
+
+/* For pseudo-dma (Sun floppy drives have no real DMA available to
+ * them so we must eat the data fifo bytes directly ourselves) we have
+ * three state variables. doing_pdma tells our inline low-level
+ * assembly floppy interrupt entry point whether it should sit and eat
+ * bytes from the fifo or just transfer control up to the higher level
+ * floppy interrupt c-code. I tried very hard but I could not get the
+ * pseudo-dma to work in c-code without getting many overruns and
+ * underruns. If non-zero, doing_pdma encodes the direction of
+ * the transfer for debugging. 1=read 2=write
+ */
+
+/* Common routines to all controller types on the Sparc. */
+static inline void virtual_dma_init(void)
+{
+ /* nothing... */
+}
+
+static inline void sun_fd_disable_dma(void)
+{
+ doing_pdma = 0;
+ pdma_base = NULL;
+}
+
+static inline void sun_fd_set_dma_mode(int mode)
+{
+ switch(mode) {
+ case DMA_MODE_READ:
+ doing_pdma = 1;
+ break;
+ case DMA_MODE_WRITE:
+ doing_pdma = 2;
+ break;
+ default:
+ printk("Unknown dma mode %d\n", mode);
+ panic("floppy: Giving up...");
+ }
+}
+
+static inline void sun_fd_set_dma_addr(char *buffer)
+{
+ pdma_vaddr = buffer;
+}
+
+static inline void sun_fd_set_dma_count(int length)
+{
+ pdma_size = length;
+}
+
+static inline void sun_fd_enable_dma(void)
+{
+ pdma_base = pdma_vaddr;
+ pdma_areasize = pdma_size;
+}
+
+int sparc_floppy_request_irq(unsigned int irq, irq_handler_t irq_handler);
+
+static int sun_fd_request_irq(void)
+{
+ static int once = 0;
+
+ if (!once) {
+ once = 1;
+ return sparc_floppy_request_irq(FLOPPY_IRQ, floppy_interrupt);
+ } else {
+ return 0;
+ }
+}
+
+static struct linux_prom_registers fd_regs[2];
+
+static int sun_floppy_init(void)
+{
+ struct platform_device *op;
+ struct device_node *dp;
+ struct resource r;
+ char state[128];
+ phandle fd_node;
+ phandle tnode;
+ int num_regs;
+
+ use_virtual_dma = 1;
+
+ /* Forget it if we aren't on a machine that could possibly
+ * ever have a floppy drive.
+ */
+ if (sparc_cpu_model != sun4m) {
+ /* We certainly don't have a floppy controller. */
+ goto no_sun_fdc;
+ }
+ /* Well, try to find one. */
+ tnode = prom_getchild(prom_root_node);
+ fd_node = prom_searchsiblings(tnode, "obio");
+ if (fd_node != 0) {
+ tnode = prom_getchild(fd_node);
+ fd_node = prom_searchsiblings(tnode, "SUNW,fdtwo");
+ } else {
+ fd_node = prom_searchsiblings(tnode, "fd");
+ }
+ if (fd_node == 0) {
+ goto no_sun_fdc;
+ }
+
+ /* The sun4m lets us know if the controller is actually usable. */
+ if (prom_getproperty(fd_node, "status", state, sizeof(state)) != -1) {
+ if(!strcmp(state, "disabled")) {
+ goto no_sun_fdc;
+ }
+ }
+ num_regs = prom_getproperty(fd_node, "reg", (char *) fd_regs, sizeof(fd_regs));
+ num_regs = (num_regs / sizeof(fd_regs[0]));
+ prom_apply_obio_ranges(fd_regs, num_regs);
+ memset(&r, 0, sizeof(r));
+ r.flags = fd_regs[0].which_io;
+ r.start = fd_regs[0].phys_addr;
+ sun_fdc = of_ioremap(&r, 0, fd_regs[0].reg_size, "floppy");
+
+ /* Look up irq in platform_device.
+ * We try "SUNW,fdtwo" and "fd"
+ */
+ op = NULL;
+ for_each_node_by_name(dp, "SUNW,fdtwo") {
+ op = of_find_device_by_node(dp);
+ if (op)
+ break;
+ }
+ if (!op) {
+ for_each_node_by_name(dp, "fd") {
+ op = of_find_device_by_node(dp);
+ if (op)
+ break;
+ }
+ }
+ if (!op)
+ goto no_sun_fdc;
+
+ FLOPPY_IRQ = op->archdata.irqs[0];
+
+ /* Last minute sanity check... */
+ if (sun_fdc->status_82072 == 0xff) {
+ sun_fdc = NULL;
+ goto no_sun_fdc;
+ }
+
+ sun_fdops.fd_inb = sun_82077_fd_inb;
+ sun_fdops.fd_outb = sun_82077_fd_outb;
+ fdc_status = &sun_fdc->status_82077;
+
+ if (sun_fdc->dor_82077 == 0x80) {
+ sun_fdc->dor_82077 = 0x02;
+ if (sun_fdc->dor_82077 == 0x80) {
+ sun_fdops.fd_inb = sun_82072_fd_inb;
+ sun_fdops.fd_outb = sun_82072_fd_outb;
+ fdc_status = &sun_fdc->status_82072;
+ }
+ }
+
+ /* Success... */
+ allowed_drive_mask = 0x01;
+ return (int) sun_fdc;
+
+no_sun_fdc:
+ return -1;
+}
+
+static int sparc_eject(void)
+{
+ set_dor(0x00, 0xff, 0x90);
+ udelay(500);
+ set_dor(0x00, 0x6f, 0x00);
+ udelay(500);
+ return 0;
+}
+
+#define fd_eject(drive) sparc_eject()
+
+#define EXTRA_FLOPPY_PARAMS
+
+static DEFINE_SPINLOCK(dma_spin_lock);
+
+#define claim_dma_lock() \
+({ unsigned long flags; \
+ spin_lock_irqsave(&dma_spin_lock, flags); \
+ flags; \
+})
+
+#define release_dma_lock(__flags) \
+ spin_unlock_irqrestore(&dma_spin_lock, __flags);
+
+#endif /* !(__ASM_SPARC_FLOPPY_H) */
diff --git a/arch/sparc/include/asm/floppy_64.h b/arch/sparc/include/asm/floppy_64.h
new file mode 100644
index 00000000000..625756406a7
--- /dev/null
+++ b/arch/sparc/include/asm/floppy_64.h
@@ -0,0 +1,774 @@
+/* floppy.h: Sparc specific parts of the Floppy driver.
+ *
+ * Copyright (C) 1996, 2007, 2008 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ *
+ * Ultra/PCI support added: Sep 1997 Eddie C. Dost (ecd@skynet.be)
+ */
+
+#ifndef __ASM_SPARC64_FLOPPY_H
+#define __ASM_SPARC64_FLOPPY_H
+
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/auxio.h>
+
+/*
+ * Define this to enable exchanging drive 0 and 1 if only drive 1 is
+ * probed on PCI machines.
+ */
+#undef PCI_FDC_SWAP_DRIVES
+
+
+/* References:
+ * 1) Netbsd Sun floppy driver.
+ * 2) NCR 82077 controller manual
+ * 3) Intel 82077 controller manual
+ */
+struct sun_flpy_controller {
+ volatile unsigned char status1_82077; /* Auxiliary Status reg. 1 */
+ volatile unsigned char status2_82077; /* Auxiliary Status reg. 2 */
+ volatile unsigned char dor_82077; /* Digital Output reg. */
+ volatile unsigned char tapectl_82077; /* Tape Control reg */
+ volatile unsigned char status_82077; /* Main Status Register. */
+#define drs_82077 status_82077 /* Digital Rate Select reg. */
+ volatile unsigned char data_82077; /* Data fifo. */
+ volatile unsigned char ___unused;
+ volatile unsigned char dir_82077; /* Digital Input reg. */
+#define dcr_82077 dir_82077 /* Config Control reg. */
+};
+
+/* You'll only ever find one controller on an Ultra anyways. */
+static struct sun_flpy_controller *sun_fdc = (struct sun_flpy_controller *)-1;
+unsigned long fdc_status;
+static struct platform_device *floppy_op = NULL;
+
+struct sun_floppy_ops {
+ unsigned char (*fd_inb) (unsigned long port);
+ void (*fd_outb) (unsigned char value, unsigned long port);
+ void (*fd_enable_dma) (void);
+ void (*fd_disable_dma) (void);
+ void (*fd_set_dma_mode) (int);
+ void (*fd_set_dma_addr) (char *);
+ void (*fd_set_dma_count) (int);
+ unsigned int (*get_dma_residue) (void);
+ int (*fd_request_irq) (void);
+ void (*fd_free_irq) (void);
+ int (*fd_eject) (int);
+};
+
+static struct sun_floppy_ops sun_fdops;
+
+#define fd_inb(port) sun_fdops.fd_inb(port)
+#define fd_outb(value,port) sun_fdops.fd_outb(value,port)
+#define fd_enable_dma() sun_fdops.fd_enable_dma()
+#define fd_disable_dma() sun_fdops.fd_disable_dma()
+#define fd_request_dma() (0) /* nothing... */
+#define fd_free_dma() /* nothing... */
+#define fd_clear_dma_ff() /* nothing... */
+#define fd_set_dma_mode(mode) sun_fdops.fd_set_dma_mode(mode)
+#define fd_set_dma_addr(addr) sun_fdops.fd_set_dma_addr(addr)
+#define fd_set_dma_count(count) sun_fdops.fd_set_dma_count(count)
+#define get_dma_residue(x) sun_fdops.get_dma_residue()
+#define fd_cacheflush(addr, size) /* nothing... */
+#define fd_request_irq() sun_fdops.fd_request_irq()
+#define fd_free_irq() sun_fdops.fd_free_irq()
+#define fd_eject(drive) sun_fdops.fd_eject(drive)
+
+/* Super paranoid... */
+#undef HAVE_DISABLE_HLT
+
+static int sun_floppy_types[2] = { 0, 0 };
+
+/* Here is where we catch the floppy driver trying to initialize,
+ * therefore this is where we call the PROM device tree probing
+ * routine etc. on the Sparc.
+ */
+#define FLOPPY0_TYPE sun_floppy_init()
+#define FLOPPY1_TYPE sun_floppy_types[1]
+
+#define FDC1 ((unsigned long)sun_fdc)
+
+#define N_FDC 1
+#define N_DRIVE 8
+
+/* No 64k boundary crossing problems on the Sparc. */
+#define CROSS_64KB(a,s) (0)
+
+static unsigned char sun_82077_fd_inb(unsigned long port)
+{
+ udelay(5);
+ switch(port & 7) {
+ default:
+ printk("floppy: Asked to read unknown port %lx\n", port);
+ panic("floppy: Port bolixed.");
+ case 4: /* FD_STATUS */
+ return sbus_readb(&sun_fdc->status_82077) & ~STATUS_DMA;
+ case 5: /* FD_DATA */
+ return sbus_readb(&sun_fdc->data_82077);
+ case 7: /* FD_DIR */
+ /* XXX: Is DCL on 0x80 in sun4m? */
+ return sbus_readb(&sun_fdc->dir_82077);
+ }
+ panic("sun_82072_fd_inb: How did I get here?");
+}
+
+static void sun_82077_fd_outb(unsigned char value, unsigned long port)
+{
+ udelay(5);
+ switch(port & 7) {
+ default:
+ printk("floppy: Asked to write to unknown port %lx\n", port);
+ panic("floppy: Port bolixed.");
+ case 2: /* FD_DOR */
+ /* Happily, the 82077 has a real DOR register. */
+ sbus_writeb(value, &sun_fdc->dor_82077);
+ break;
+ case 5: /* FD_DATA */
+ sbus_writeb(value, &sun_fdc->data_82077);
+ break;
+ case 7: /* FD_DCR */
+ sbus_writeb(value, &sun_fdc->dcr_82077);
+ break;
+ case 4: /* FD_STATUS */
+ sbus_writeb(value, &sun_fdc->status_82077);
+ break;
+ }
+ return;
+}
+
+/* For pseudo-dma (Sun floppy drives have no real DMA available to
+ * them so we must eat the data fifo bytes directly ourselves) we have
+ * three state variables. doing_pdma tells our inline low-level
+ * assembly floppy interrupt entry point whether it should sit and eat
+ * bytes from the fifo or just transfer control up to the higher level
+ * floppy interrupt c-code. I tried very hard but I could not get the
+ * pseudo-dma to work in c-code without getting many overruns and
+ * underruns. If non-zero, doing_pdma encodes the direction of
+ * the transfer for debugging. 1=read 2=write
+ */
+unsigned char *pdma_vaddr;
+unsigned long pdma_size;
+volatile int doing_pdma = 0;
+
+/* This is software state */
+char *pdma_base = NULL;
+unsigned long pdma_areasize;
+
+/* Common routines to all controller types on the Sparc. */
+static void sun_fd_disable_dma(void)
+{
+ doing_pdma = 0;
+ pdma_base = NULL;
+}
+
+static void sun_fd_set_dma_mode(int mode)
+{
+ switch(mode) {
+ case DMA_MODE_READ:
+ doing_pdma = 1;
+ break;
+ case DMA_MODE_WRITE:
+ doing_pdma = 2;
+ break;
+ default:
+ printk("Unknown dma mode %d\n", mode);
+ panic("floppy: Giving up...");
+ }
+}
+
+static void sun_fd_set_dma_addr(char *buffer)
+{
+ pdma_vaddr = buffer;
+}
+
+static void sun_fd_set_dma_count(int length)
+{
+ pdma_size = length;
+}
+
+static void sun_fd_enable_dma(void)
+{
+ pdma_base = pdma_vaddr;
+ pdma_areasize = pdma_size;
+}
+
+irqreturn_t sparc_floppy_irq(int irq, void *dev_cookie)
+{
+ if (likely(doing_pdma)) {
+ void __iomem *stat = (void __iomem *) fdc_status;
+ unsigned char *vaddr = pdma_vaddr;
+ unsigned long size = pdma_size;
+ u8 val;
+
+ while (size) {
+ val = readb(stat);
+ if (unlikely(!(val & 0x80))) {
+ pdma_vaddr = vaddr;
+ pdma_size = size;
+ return IRQ_HANDLED;
+ }
+ if (unlikely(!(val & 0x20))) {
+ pdma_vaddr = vaddr;
+ pdma_size = size;
+ doing_pdma = 0;
+ goto main_interrupt;
+ }
+ if (val & 0x40) {
+ /* read */
+ *vaddr++ = readb(stat + 1);
+ } else {
+ unsigned char data = *vaddr++;
+
+ /* write */
+ writeb(data, stat + 1);
+ }
+ size--;
+ }
+
+ pdma_vaddr = vaddr;
+ pdma_size = size;
+
+ /* Send Terminal Count pulse to floppy controller. */
+ val = readb(auxio_register);
+ val |= AUXIO_AUX1_FTCNT;
+ writeb(val, auxio_register);
+ val &= ~AUXIO_AUX1_FTCNT;
+ writeb(val, auxio_register);
+
+ doing_pdma = 0;
+ }
+
+main_interrupt:
+ return floppy_interrupt(irq, dev_cookie);
+}
+
+static int sun_fd_request_irq(void)
+{
+ static int once = 0;
+ int error;
+
+ if(!once) {
+ once = 1;
+
+ error = request_irq(FLOPPY_IRQ, sparc_floppy_irq,
+ 0, "floppy", NULL);
+
+ return ((error == 0) ? 0 : -1);
+ }
+ return 0;
+}
+
+static void sun_fd_free_irq(void)
+{
+}
+
+static unsigned int sun_get_dma_residue(void)
+{
+ /* XXX This isn't really correct. XXX */
+ return 0;
+}
+
+static int sun_fd_eject(int drive)
+{
+ set_dor(0x00, 0xff, 0x90);
+ udelay(500);
+ set_dor(0x00, 0x6f, 0x00);
+ udelay(500);
+ return 0;
+}
+
+#include <asm/ebus_dma.h>
+#include <asm/ns87303.h>
+
+static struct ebus_dma_info sun_pci_fd_ebus_dma;
+static struct device *sun_floppy_dev;
+static int sun_pci_broken_drive = -1;
+
+struct sun_pci_dma_op {
+ unsigned int addr;
+ int len;
+ int direction;
+ char *buf;
+};
+static struct sun_pci_dma_op sun_pci_dma_current = { -1U, 0, 0, NULL};
+static struct sun_pci_dma_op sun_pci_dma_pending = { -1U, 0, 0, NULL};
+
+irqreturn_t floppy_interrupt(int irq, void *dev_id);
+
+static unsigned char sun_pci_fd_inb(unsigned long port)
+{
+ udelay(5);
+ return inb(port);
+}
+
+static void sun_pci_fd_outb(unsigned char val, unsigned long port)
+{
+ udelay(5);
+ outb(val, port);
+}
+
+static void sun_pci_fd_broken_outb(unsigned char val, unsigned long port)
+{
+ udelay(5);
+ /*
+ * XXX: Due to SUN's broken floppy connector on AX and AXi
+ * we need to turn on MOTOR_0 also, if the floppy is
+ * jumpered to DS1 (like most PC floppies are). I hope
+ * this does not hurt correct hardware like the AXmp.
+ * (Eddie, Sep 12 1998).
+ */
+ if (port == ((unsigned long)sun_fdc) + 2) {
+ if (((val & 0x03) == sun_pci_broken_drive) && (val & 0x20)) {
+ val |= 0x10;
+ }
+ }
+ outb(val, port);
+}
+
+#ifdef PCI_FDC_SWAP_DRIVES
+static void sun_pci_fd_lde_broken_outb(unsigned char val, unsigned long port)
+{
+ udelay(5);
+ /*
+ * XXX: Due to SUN's broken floppy connector on AX and AXi
+ * we need to turn on MOTOR_0 also, if the floppy is
+ * jumpered to DS1 (like most PC floppies are). I hope
+ * this does not hurt correct hardware like the AXmp.
+ * (Eddie, Sep 12 1998).
+ */
+ if (port == ((unsigned long)sun_fdc) + 2) {
+ if (((val & 0x03) == sun_pci_broken_drive) && (val & 0x10)) {
+ val &= ~(0x03);
+ val |= 0x21;
+ }
+ }
+ outb(val, port);
+}
+#endif /* PCI_FDC_SWAP_DRIVES */
+
+static void sun_pci_fd_enable_dma(void)
+{
+ BUG_ON((NULL == sun_pci_dma_pending.buf) ||
+ (0 == sun_pci_dma_pending.len) ||
+ (0 == sun_pci_dma_pending.direction));
+
+ sun_pci_dma_current.buf = sun_pci_dma_pending.buf;
+ sun_pci_dma_current.len = sun_pci_dma_pending.len;
+ sun_pci_dma_current.direction = sun_pci_dma_pending.direction;
+
+ sun_pci_dma_pending.buf = NULL;
+ sun_pci_dma_pending.len = 0;
+ sun_pci_dma_pending.direction = 0;
+ sun_pci_dma_pending.addr = -1U;
+
+ sun_pci_dma_current.addr =
+ dma_map_single(sun_floppy_dev,
+ sun_pci_dma_current.buf,
+ sun_pci_dma_current.len,
+ sun_pci_dma_current.direction);
+
+ ebus_dma_enable(&sun_pci_fd_ebus_dma, 1);
+
+ if (ebus_dma_request(&sun_pci_fd_ebus_dma,
+ sun_pci_dma_current.addr,
+ sun_pci_dma_current.len))
+ BUG();
+}
+
+static void sun_pci_fd_disable_dma(void)
+{
+ ebus_dma_enable(&sun_pci_fd_ebus_dma, 0);
+ if (sun_pci_dma_current.addr != -1U)
+ dma_unmap_single(sun_floppy_dev,
+ sun_pci_dma_current.addr,
+ sun_pci_dma_current.len,
+ sun_pci_dma_current.direction);
+ sun_pci_dma_current.addr = -1U;
+}
+
+static void sun_pci_fd_set_dma_mode(int mode)
+{
+ if (mode == DMA_MODE_WRITE)
+ sun_pci_dma_pending.direction = DMA_TO_DEVICE;
+ else
+ sun_pci_dma_pending.direction = DMA_FROM_DEVICE;
+
+ ebus_dma_prepare(&sun_pci_fd_ebus_dma, mode != DMA_MODE_WRITE);
+}
+
+static void sun_pci_fd_set_dma_count(int length)
+{
+ sun_pci_dma_pending.len = length;
+}
+
+static void sun_pci_fd_set_dma_addr(char *buffer)
+{
+ sun_pci_dma_pending.buf = buffer;
+}
+
+static unsigned int sun_pci_get_dma_residue(void)
+{
+ return ebus_dma_residue(&sun_pci_fd_ebus_dma);
+}
+
+static int sun_pci_fd_request_irq(void)
+{
+ return ebus_dma_irq_enable(&sun_pci_fd_ebus_dma, 1);
+}
+
+static void sun_pci_fd_free_irq(void)
+{
+ ebus_dma_irq_enable(&sun_pci_fd_ebus_dma, 0);
+}
+
+static int sun_pci_fd_eject(int drive)
+{
+ return -EINVAL;
+}
+
+void sun_pci_fd_dma_callback(struct ebus_dma_info *p, int event, void *cookie)
+{
+ floppy_interrupt(0, NULL);
+}
+
+/*
+ * Floppy probing, we'd like to use /dev/fd0 for a single Floppy on PCI,
+ * even if this is configured using DS1, thus looks like /dev/fd1 with
+ * the cabling used in Ultras.
+ */
+#define DOR (port + 2)
+#define MSR (port + 4)
+#define FIFO (port + 5)
+
+static void sun_pci_fd_out_byte(unsigned long port, unsigned char val,
+ unsigned long reg)
+{
+ unsigned char status;
+ int timeout = 1000;
+
+ while (!((status = inb(MSR)) & 0x80) && --timeout)
+ udelay(100);
+ outb(val, reg);
+}
+
+static unsigned char sun_pci_fd_sensei(unsigned long port)
+{
+ unsigned char result[2] = { 0x70, 0x00 };
+ unsigned char status;
+ int i = 0;
+
+ sun_pci_fd_out_byte(port, 0x08, FIFO);
+ do {
+ int timeout = 1000;
+
+ while (!((status = inb(MSR)) & 0x80) && --timeout)
+ udelay(100);
+
+ if (!timeout)
+ break;
+
+ if ((status & 0xf0) == 0xd0)
+ result[i++] = inb(FIFO);
+ else
+ break;
+ } while (i < 2);
+
+ return result[0];
+}
+
+static void sun_pci_fd_reset(unsigned long port)
+{
+ unsigned char mask = 0x00;
+ unsigned char status;
+ int timeout = 10000;
+
+ outb(0x80, MSR);
+ do {
+ status = sun_pci_fd_sensei(port);
+ if ((status & 0xc0) == 0xc0)
+ mask |= 1 << (status & 0x03);
+ else
+ udelay(100);
+ } while ((mask != 0x0f) && --timeout);
+}
+
+static int sun_pci_fd_test_drive(unsigned long port, int drive)
+{
+ unsigned char status, data;
+ int timeout = 1000;
+ int ready;
+
+ sun_pci_fd_reset(port);
+
+ data = (0x10 << drive) | 0x0c | drive;
+ sun_pci_fd_out_byte(port, data, DOR);
+
+ sun_pci_fd_out_byte(port, 0x07, FIFO);
+ sun_pci_fd_out_byte(port, drive & 0x03, FIFO);
+
+ do {
+ udelay(100);
+ status = sun_pci_fd_sensei(port);
+ } while (((status & 0xc0) == 0x80) && --timeout);
+
+ if (!timeout)
+ ready = 0;
+ else
+ ready = (status & 0x10) ? 0 : 1;
+
+ sun_pci_fd_reset(port);
+ return ready;
+}
+#undef FIFO
+#undef MSR
+#undef DOR
+
+static int __init ebus_fdthree_p(struct device_node *dp)
+{
+ if (!strcmp(dp->name, "fdthree"))
+ return 1;
+ if (!strcmp(dp->name, "floppy")) {
+ const char *compat;
+
+ compat = of_get_property(dp, "compatible", NULL);
+ if (compat && !strcmp(compat, "fdthree"))
+ return 1;
+ }
+ return 0;
+}
+
+static unsigned long __init sun_floppy_init(void)
+{
+ static int initialized = 0;
+ struct device_node *dp;
+ struct platform_device *op;
+ const char *prop;
+ char state[128];
+
+ if (initialized)
+ return sun_floppy_types[0];
+ initialized = 1;
+
+ op = NULL;
+
+ for_each_node_by_name(dp, "SUNW,fdtwo") {
+ if (strcmp(dp->parent->name, "sbus"))
+ continue;
+ op = of_find_device_by_node(dp);
+ if (op)
+ break;
+ }
+ if (op) {
+ floppy_op = op;
+ FLOPPY_IRQ = op->archdata.irqs[0];
+ } else {
+ struct device_node *ebus_dp;
+ void __iomem *auxio_reg;
+ const char *state_prop;
+ unsigned long config;
+
+ dp = NULL;
+ for_each_node_by_name(ebus_dp, "ebus") {
+ for (dp = ebus_dp->child; dp; dp = dp->sibling) {
+ if (ebus_fdthree_p(dp))
+ goto found_fdthree;
+ }
+ }
+ found_fdthree:
+ if (!dp)
+ return 0;
+
+ op = of_find_device_by_node(dp);
+ if (!op)
+ return 0;
+
+ state_prop = of_get_property(op->dev.of_node, "status", NULL);
+ if (state_prop && !strncmp(state_prop, "disabled", 8))
+ return 0;
+
+ FLOPPY_IRQ = op->archdata.irqs[0];
+
+ /* Make sure the high density bit is set, some systems
+ * (most notably Ultra5/Ultra10) come up with it clear.
+ */
+ auxio_reg = (void __iomem *) op->resource[2].start;
+ writel(readl(auxio_reg)|0x2, auxio_reg);
+
+ sun_floppy_dev = &op->dev;
+
+ spin_lock_init(&sun_pci_fd_ebus_dma.lock);
+
+ /* XXX ioremap */
+ sun_pci_fd_ebus_dma.regs = (void __iomem *)
+ op->resource[1].start;
+ if (!sun_pci_fd_ebus_dma.regs)
+ return 0;
+
+ sun_pci_fd_ebus_dma.flags = (EBUS_DMA_FLAG_USE_EBDMA_HANDLER |
+ EBUS_DMA_FLAG_TCI_DISABLE);
+ sun_pci_fd_ebus_dma.callback = sun_pci_fd_dma_callback;
+ sun_pci_fd_ebus_dma.client_cookie = NULL;
+ sun_pci_fd_ebus_dma.irq = FLOPPY_IRQ;
+ strcpy(sun_pci_fd_ebus_dma.name, "floppy");
+ if (ebus_dma_register(&sun_pci_fd_ebus_dma))
+ return 0;
+
+ /* XXX ioremap */
+ sun_fdc = (struct sun_flpy_controller *) op->resource[0].start;
+
+ sun_fdops.fd_inb = sun_pci_fd_inb;
+ sun_fdops.fd_outb = sun_pci_fd_outb;
+
+ can_use_virtual_dma = use_virtual_dma = 0;
+ sun_fdops.fd_enable_dma = sun_pci_fd_enable_dma;
+ sun_fdops.fd_disable_dma = sun_pci_fd_disable_dma;
+ sun_fdops.fd_set_dma_mode = sun_pci_fd_set_dma_mode;
+ sun_fdops.fd_set_dma_addr = sun_pci_fd_set_dma_addr;
+ sun_fdops.fd_set_dma_count = sun_pci_fd_set_dma_count;
+ sun_fdops.get_dma_residue = sun_pci_get_dma_residue;
+
+ sun_fdops.fd_request_irq = sun_pci_fd_request_irq;
+ sun_fdops.fd_free_irq = sun_pci_fd_free_irq;
+
+ sun_fdops.fd_eject = sun_pci_fd_eject;
+
+ fdc_status = (unsigned long) &sun_fdc->status_82077;
+
+ /*
+ * XXX: Find out on which machines this is really needed.
+ */
+ if (1) {
+ sun_pci_broken_drive = 1;
+ sun_fdops.fd_outb = sun_pci_fd_broken_outb;
+ }
+
+ allowed_drive_mask = 0;
+ if (sun_pci_fd_test_drive((unsigned long)sun_fdc, 0))
+ sun_floppy_types[0] = 4;
+ if (sun_pci_fd_test_drive((unsigned long)sun_fdc, 1))
+ sun_floppy_types[1] = 4;
+
+ /*
+ * Find NS87303 SuperIO config registers (through ecpp).
+ */
+ config = 0;
+ for (dp = ebus_dp->child; dp; dp = dp->sibling) {
+ if (!strcmp(dp->name, "ecpp")) {
+ struct platform_device *ecpp_op;
+
+ ecpp_op = of_find_device_by_node(dp);
+ if (ecpp_op)
+ config = ecpp_op->resource[1].start;
+ goto config_done;
+ }
+ }
+ config_done:
+
+ /*
+ * Sanity check, is this really the NS87303?
+ */
+ switch (config & 0x3ff) {
+ case 0x02e:
+ case 0x15c:
+ case 0x26e:
+ case 0x398:
+ break;
+ default:
+ config = 0;
+ }
+
+ if (!config)
+ return sun_floppy_types[0];
+
+ /* Enable PC-AT mode. */
+ ns87303_modify(config, ASC, 0, 0xc0);
+
+#ifdef PCI_FDC_SWAP_DRIVES
+ /*
+ * If only Floppy 1 is present, swap drives.
+ */
+ if (!sun_floppy_types[0] && sun_floppy_types[1]) {
+ /*
+ * Set the drive exchange bit in FCR on NS87303,
+ * make sure other bits are sane before doing so.
+ */
+ ns87303_modify(config, FER, FER_EDM, 0);
+ ns87303_modify(config, ASC, ASC_DRV2_SEL, 0);
+ ns87303_modify(config, FCR, 0, FCR_LDE);
+
+ config = sun_floppy_types[0];
+ sun_floppy_types[0] = sun_floppy_types[1];
+ sun_floppy_types[1] = config;
+
+ if (sun_pci_broken_drive != -1) {
+ sun_pci_broken_drive = 1 - sun_pci_broken_drive;
+ sun_fdops.fd_outb = sun_pci_fd_lde_broken_outb;
+ }
+ }
+#endif /* PCI_FDC_SWAP_DRIVES */
+
+ return sun_floppy_types[0];
+ }
+ prop = of_get_property(op->dev.of_node, "status", NULL);
+ if (prop && !strncmp(state, "disabled", 8))
+ return 0;
+
+ /*
+ * We cannot do of_ioremap here: it does request_region,
+ * which the generic floppy driver tries to do once again.
+ * But we must use the sdev resource values as they have
+ * had parent ranges applied.
+ */
+ sun_fdc = (struct sun_flpy_controller *)
+ (op->resource[0].start +
+ ((op->resource[0].flags & 0x1ffUL) << 32UL));
+
+ /* Last minute sanity check... */
+ if (sbus_readb(&sun_fdc->status1_82077) == 0xff) {
+ sun_fdc = (struct sun_flpy_controller *)-1;
+ return 0;
+ }
+
+ sun_fdops.fd_inb = sun_82077_fd_inb;
+ sun_fdops.fd_outb = sun_82077_fd_outb;
+
+ can_use_virtual_dma = use_virtual_dma = 1;
+ sun_fdops.fd_enable_dma = sun_fd_enable_dma;
+ sun_fdops.fd_disable_dma = sun_fd_disable_dma;
+ sun_fdops.fd_set_dma_mode = sun_fd_set_dma_mode;
+ sun_fdops.fd_set_dma_addr = sun_fd_set_dma_addr;
+ sun_fdops.fd_set_dma_count = sun_fd_set_dma_count;
+ sun_fdops.get_dma_residue = sun_get_dma_residue;
+
+ sun_fdops.fd_request_irq = sun_fd_request_irq;
+ sun_fdops.fd_free_irq = sun_fd_free_irq;
+
+ sun_fdops.fd_eject = sun_fd_eject;
+
+ fdc_status = (unsigned long) &sun_fdc->status_82077;
+
+ /* Success... */
+ allowed_drive_mask = 0x01;
+ sun_floppy_types[0] = 4;
+ sun_floppy_types[1] = 0;
+
+ return sun_floppy_types[0];
+}
+
+#define EXTRA_FLOPPY_PARAMS
+
+static DEFINE_SPINLOCK(dma_spin_lock);
+
+#define claim_dma_lock() \
+({ unsigned long flags; \
+ spin_lock_irqsave(&dma_spin_lock, flags); \
+ flags; \
+})
+
+#define release_dma_lock(__flags) \
+ spin_unlock_irqrestore(&dma_spin_lock, __flags);
+
+#endif /* !(__ASM_SPARC64_FLOPPY_H) */
diff --git a/arch/sparc/include/asm/fpumacro.h b/arch/sparc/include/asm/fpumacro.h
new file mode 100644
index 00000000000..cc463fec806
--- /dev/null
+++ b/arch/sparc/include/asm/fpumacro.h
@@ -0,0 +1,33 @@
+/* fpumacro.h: FPU related macros.
+ *
+ * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _SPARC64_FPUMACRO_H
+#define _SPARC64_FPUMACRO_H
+
+#include <asm/asi.h>
+#include <asm/visasm.h>
+
+struct fpustate {
+ u32 regs[64];
+};
+
+#define FPUSTATE (struct fpustate *)(current_thread_info()->fpregs)
+
+static inline unsigned long fprs_read(void)
+{
+ unsigned long retval;
+
+ __asm__ __volatile__("rd %%fprs, %0" : "=r" (retval));
+
+ return retval;
+}
+
+static inline void fprs_write(unsigned long val)
+{
+ __asm__ __volatile__("wr %0, 0x0, %%fprs" : : "r" (val));
+}
+
+#endif /* !(_SPARC64_FPUMACRO_H) */
diff --git a/arch/sparc/include/asm/ftrace.h b/arch/sparc/include/asm/ftrace.h
new file mode 100644
index 00000000000..9ec94ad116f
--- /dev/null
+++ b/arch/sparc/include/asm/ftrace.h
@@ -0,0 +1,29 @@
+#ifndef _ASM_SPARC64_FTRACE
+#define _ASM_SPARC64_FTRACE
+
+#ifdef CONFIG_MCOUNT
+#define MCOUNT_ADDR ((long)(_mcount))
+#define MCOUNT_INSN_SIZE 4 /* sizeof mcount call */
+
+#ifndef __ASSEMBLY__
+void _mcount(void);
+#endif
+
+#endif
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+/* reloction of mcount call site is the same as the address */
+static inline unsigned long ftrace_call_adjust(unsigned long addr)
+{
+ return addr;
+}
+
+struct dyn_arch_ftrace {
+};
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
+unsigned long prepare_ftrace_return(unsigned long parent,
+ unsigned long self_addr,
+ unsigned long frame_pointer);
+
+#endif /* _ASM_SPARC64_FTRACE */
diff --git a/arch/sparc/include/asm/futex.h b/arch/sparc/include/asm/futex.h
new file mode 100644
index 00000000000..736335f3671
--- /dev/null
+++ b/arch/sparc/include/asm/futex.h
@@ -0,0 +1,8 @@
+#ifndef ___ASM_SPARC_FUTEX_H
+#define ___ASM_SPARC_FUTEX_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/futex_64.h>
+#else
+#include <asm/futex_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/futex_32.h b/arch/sparc/include/asm/futex_32.h
new file mode 100644
index 00000000000..6a332a9f099
--- /dev/null
+++ b/arch/sparc/include/asm/futex_32.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#include <asm-generic/futex.h>
+
+#endif
diff --git a/arch/sparc/include/asm/futex_64.h b/arch/sparc/include/asm/futex_64.h
new file mode 100644
index 00000000000..4e899b0dabf
--- /dev/null
+++ b/arch/sparc/include/asm/futex_64.h
@@ -0,0 +1,113 @@
+#ifndef _SPARC64_FUTEX_H
+#define _SPARC64_FUTEX_H
+
+#include <linux/futex.h>
+#include <linux/uaccess.h>
+#include <asm/errno.h>
+
+#define __futex_cas_op(insn, ret, oldval, uaddr, oparg) \
+ __asm__ __volatile__( \
+ "\n1: lduwa [%3] %%asi, %2\n" \
+ " " insn "\n" \
+ "2: casa [%3] %%asi, %2, %1\n" \
+ " cmp %2, %1\n" \
+ " bne,pn %%icc, 1b\n" \
+ " mov 0, %0\n" \
+ "3:\n" \
+ " .section .fixup,#alloc,#execinstr\n" \
+ " .align 4\n" \
+ "4: sethi %%hi(3b), %0\n" \
+ " jmpl %0 + %%lo(3b), %%g0\n" \
+ " mov %5, %0\n" \
+ " .previous\n" \
+ " .section __ex_table,\"a\"\n" \
+ " .align 4\n" \
+ " .word 1b, 4b\n" \
+ " .word 2b, 4b\n" \
+ " .previous\n" \
+ : "=&r" (ret), "=&r" (oldval), "=&r" (tem) \
+ : "r" (uaddr), "r" (oparg), "i" (-EFAULT) \
+ : "memory")
+
+static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
+{
+ int op = (encoded_op >> 28) & 7;
+ int cmp = (encoded_op >> 24) & 15;
+ int oparg = (encoded_op << 8) >> 20;
+ int cmparg = (encoded_op << 20) >> 20;
+ int oldval = 0, ret, tem;
+
+ if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))))
+ return -EFAULT;
+ if (unlikely((((unsigned long) uaddr) & 0x3UL)))
+ return -EINVAL;
+
+ if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+ oparg = 1 << oparg;
+
+ pagefault_disable();
+
+ switch (op) {
+ case FUTEX_OP_SET:
+ __futex_cas_op("mov\t%4, %1", ret, oldval, uaddr, oparg);
+ break;
+ case FUTEX_OP_ADD:
+ __futex_cas_op("add\t%2, %4, %1", ret, oldval, uaddr, oparg);
+ break;
+ case FUTEX_OP_OR:
+ __futex_cas_op("or\t%2, %4, %1", ret, oldval, uaddr, oparg);
+ break;
+ case FUTEX_OP_ANDN:
+ __futex_cas_op("andn\t%2, %4, %1", ret, oldval, uaddr, oparg);
+ break;
+ case FUTEX_OP_XOR:
+ __futex_cas_op("xor\t%2, %4, %1", ret, oldval, uaddr, oparg);
+ break;
+ default:
+ ret = -ENOSYS;
+ }
+
+ pagefault_enable();
+
+ if (!ret) {
+ switch (cmp) {
+ case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+ case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+ case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+ case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+ case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+ case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+ default: ret = -ENOSYS;
+ }
+ }
+ return ret;
+}
+
+static inline int
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+ u32 oldval, u32 newval)
+{
+ int ret = 0;
+
+ __asm__ __volatile__(
+ "\n1: casa [%4] %%asi, %3, %1\n"
+ "2:\n"
+ " .section .fixup,#alloc,#execinstr\n"
+ " .align 4\n"
+ "3: sethi %%hi(2b), %0\n"
+ " jmpl %0 + %%lo(2b), %%g0\n"
+ " mov %5, %0\n"
+ " .previous\n"
+ " .section __ex_table,\"a\"\n"
+ " .align 4\n"
+ " .word 1b, 3b\n"
+ " .previous\n"
+ : "+r" (ret), "=r" (newval)
+ : "1" (newval), "r" (oldval), "r" (uaddr), "i" (-EFAULT)
+ : "memory");
+
+ *uval = newval;
+ return ret;
+}
+
+#endif /* !(_SPARC64_FUTEX_H) */
diff --git a/arch/sparc/include/asm/gpio.h b/arch/sparc/include/asm/gpio.h
new file mode 100644
index 00000000000..b3799d88ffc
--- /dev/null
+++ b/arch/sparc/include/asm/gpio.h
@@ -0,0 +1,4 @@
+#ifndef __LINUX_GPIO_H
+#warning Include linux/gpio.h instead of asm/gpio.h
+#include <linux/gpio.h>
+#endif
diff --git a/arch/sparc/include/asm/hardirq.h b/arch/sparc/include/asm/hardirq.h
new file mode 100644
index 00000000000..44d4e234514
--- /dev/null
+++ b/arch/sparc/include/asm/hardirq.h
@@ -0,0 +1,8 @@
+#ifndef ___ASM_SPARC_HARDIRQ_H
+#define ___ASM_SPARC_HARDIRQ_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/hardirq_64.h>
+#else
+#include <asm/hardirq_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/hardirq_32.h b/arch/sparc/include/asm/hardirq_32.h
new file mode 100644
index 00000000000..ee93923b7f8
--- /dev/null
+++ b/arch/sparc/include/asm/hardirq_32.h
@@ -0,0 +1,12 @@
+/* hardirq.h: 32-bit Sparc hard IRQ support.
+ *
+ * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1998-2000 Anton Blanchard (anton@samba.org)
+ */
+
+#ifndef __SPARC_HARDIRQ_H
+#define __SPARC_HARDIRQ_H
+
+#include <asm-generic/hardirq.h>
+
+#endif /* __SPARC_HARDIRQ_H */
diff --git a/arch/sparc/include/asm/hardirq_64.h b/arch/sparc/include/asm/hardirq_64.h
new file mode 100644
index 00000000000..f478ff1ddd0
--- /dev/null
+++ b/arch/sparc/include/asm/hardirq_64.h
@@ -0,0 +1,17 @@
+/* hardirq.h: 64-bit Sparc hard IRQ support.
+ *
+ * Copyright (C) 1997, 1998, 2005 David S. Miller (davem@davemloft.net)
+ */
+
+#ifndef __SPARC64_HARDIRQ_H
+#define __SPARC64_HARDIRQ_H
+
+#include <asm/cpudata.h>
+
+#define __ARCH_IRQ_STAT
+#define local_softirq_pending() \
+ (local_cpu_data().__softirq_pending)
+
+void ack_bad_irq(unsigned int irq);
+
+#endif /* !(__SPARC64_HARDIRQ_H) */
diff --git a/arch/sparc/include/asm/head.h b/arch/sparc/include/asm/head.h
new file mode 100644
index 00000000000..be8f03f3e73
--- /dev/null
+++ b/arch/sparc/include/asm/head.h
@@ -0,0 +1,8 @@
+#ifndef ___ASM_SPARC_HEAD_H
+#define ___ASM_SPARC_HEAD_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/head_64.h>
+#else
+#include <asm/head_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/head_32.h b/arch/sparc/include/asm/head_32.h
new file mode 100644
index 00000000000..5f1dbe315bc
--- /dev/null
+++ b/arch/sparc/include/asm/head_32.h
@@ -0,0 +1,83 @@
+#ifndef __SPARC_HEAD_H
+#define __SPARC_HEAD_H
+
+#define KERNBASE 0xf0000000 /* First address the kernel will eventually be */
+
+#define WRITE_PAUSE nop; nop; nop; /* Have to do this after %wim/%psr chg */
+
+/* Here are some trap goodies */
+
+/* Generic trap entry. */
+#define TRAP_ENTRY(type, label) \
+ rd %psr, %l0; b label; rd %wim, %l3; nop;
+
+/* Data/text faults */
+#define SRMMU_TFAULT rd %psr, %l0; rd %wim, %l3; b srmmu_fault; mov 1, %l7;
+#define SRMMU_DFAULT rd %psr, %l0; rd %wim, %l3; b srmmu_fault; mov 0, %l7;
+
+/* This is for traps we should NEVER get. */
+#define BAD_TRAP(num) \
+ rd %psr, %l0; mov num, %l7; b bad_trap_handler; rd %wim, %l3;
+
+/* This is for traps when we want just skip the instruction which caused it */
+#define SKIP_TRAP(type, name) \
+ jmpl %l2, %g0; rett %l2 + 4; nop; nop;
+
+/* Notice that for the system calls we pull a trick. We load up a
+ * different pointer to the system call vector table in %l7, but call
+ * the same generic system call low-level entry point. The trap table
+ * entry sequences are also HyperSparc pipeline friendly ;-)
+ */
+
+/* Software trap for Linux system calls. */
+#define LINUX_SYSCALL_TRAP \
+ sethi %hi(sys_call_table), %l7; \
+ or %l7, %lo(sys_call_table), %l7; \
+ b linux_sparc_syscall; \
+ rd %psr, %l0;
+
+#define BREAKPOINT_TRAP \
+ b breakpoint_trap; \
+ rd %psr,%l0; \
+ nop; \
+ nop;
+
+#ifdef CONFIG_KGDB
+#define KGDB_TRAP(num) \
+ b kgdb_trap_low; \
+ rd %psr,%l0; \
+ nop; \
+ nop;
+#else
+#define KGDB_TRAP(num) \
+ BAD_TRAP(num)
+#endif
+
+/* The Get Condition Codes software trap for userland. */
+#define GETCC_TRAP \
+ b getcc_trap_handler; rd %psr, %l0; nop; nop;
+
+/* The Set Condition Codes software trap for userland. */
+#define SETCC_TRAP \
+ b setcc_trap_handler; rd %psr, %l0; nop; nop;
+
+/* The Get PSR software trap for userland. */
+#define GETPSR_TRAP \
+ rd %psr, %i0; jmp %l2; rett %l2 + 4; nop;
+
+/* This is for hard interrupts from level 1-14, 15 is non-maskable (nmi) and
+ * gets handled with another macro.
+ */
+#define TRAP_ENTRY_INTERRUPT(int_level) \
+ mov int_level, %l7; rd %psr, %l0; b real_irq_entry; rd %wim, %l3;
+
+/* Window overflows/underflows are special and we need to try to be as
+ * efficient as possible here....
+ */
+#define WINDOW_SPILL \
+ rd %psr, %l0; rd %wim, %l3; b spill_window_entry; andcc %l0, PSR_PS, %g0;
+
+#define WINDOW_FILL \
+ rd %psr, %l0; rd %wim, %l3; b fill_window_entry; andcc %l0, PSR_PS, %g0;
+
+#endif /* __SPARC_HEAD_H */
diff --git a/arch/sparc/include/asm/head_64.h b/arch/sparc/include/asm/head_64.h
new file mode 100644
index 00000000000..10e9dabc4c4
--- /dev/null
+++ b/arch/sparc/include/asm/head_64.h
@@ -0,0 +1,76 @@
+#ifndef _SPARC64_HEAD_H
+#define _SPARC64_HEAD_H
+
+#include <asm/pstate.h>
+
+ /* wrpr %g0, val, %gl */
+#define SET_GL(val) \
+ .word 0xa1902000 | val
+
+ /* rdpr %gl, %gN */
+#define GET_GL_GLOBAL(N) \
+ .word 0x81540000 | (N << 25)
+
+#define KERNBASE 0x400000
+
+#define PTREGS_OFF (STACK_BIAS + STACKFRAME_SZ)
+
+#define __CHEETAH_ID 0x003e0014
+#define __JALAPENO_ID 0x003e0016
+#define __SERRANO_ID 0x003e0022
+
+#define CHEETAH_MANUF 0x003e
+#define CHEETAH_IMPL 0x0014 /* Ultra-III */
+#define CHEETAH_PLUS_IMPL 0x0015 /* Ultra-III+ */
+#define JALAPENO_IMPL 0x0016 /* Ultra-IIIi */
+#define JAGUAR_IMPL 0x0018 /* Ultra-IV */
+#define PANTHER_IMPL 0x0019 /* Ultra-IV+ */
+#define SERRANO_IMPL 0x0022 /* Ultra-IIIi+ */
+
+#define BRANCH_IF_SUN4V(tmp1,label) \
+ sethi %hi(is_sun4v), %tmp1; \
+ lduw [%tmp1 + %lo(is_sun4v)], %tmp1; \
+ brnz,pn %tmp1, label; \
+ nop
+
+#define BRANCH_IF_CHEETAH_BASE(tmp1,tmp2,label) \
+ rdpr %ver, %tmp1; \
+ sethi %hi(__CHEETAH_ID), %tmp2; \
+ srlx %tmp1, 32, %tmp1; \
+ or %tmp2, %lo(__CHEETAH_ID), %tmp2;\
+ cmp %tmp1, %tmp2; \
+ be,pn %icc, label; \
+ nop;
+
+#define BRANCH_IF_JALAPENO(tmp1,tmp2,label) \
+ rdpr %ver, %tmp1; \
+ sethi %hi(__JALAPENO_ID), %tmp2; \
+ srlx %tmp1, 32, %tmp1; \
+ or %tmp2, %lo(__JALAPENO_ID), %tmp2;\
+ cmp %tmp1, %tmp2; \
+ be,pn %icc, label; \
+ nop;
+
+#define BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(tmp1,tmp2,label) \
+ rdpr %ver, %tmp1; \
+ srlx %tmp1, (32 + 16), %tmp2; \
+ cmp %tmp2, CHEETAH_MANUF; \
+ bne,pt %xcc, 99f; \
+ sllx %tmp1, 16, %tmp1; \
+ srlx %tmp1, (32 + 16), %tmp2; \
+ cmp %tmp2, CHEETAH_PLUS_IMPL; \
+ bgeu,pt %xcc, label; \
+99: nop;
+
+#define BRANCH_IF_ANY_CHEETAH(tmp1,tmp2,label) \
+ rdpr %ver, %tmp1; \
+ srlx %tmp1, (32 + 16), %tmp2; \
+ cmp %tmp2, CHEETAH_MANUF; \
+ bne,pt %xcc, 99f; \
+ sllx %tmp1, 16, %tmp1; \
+ srlx %tmp1, (32 + 16), %tmp2; \
+ cmp %tmp2, CHEETAH_IMPL; \
+ bgeu,pt %xcc, label; \
+99: nop;
+
+#endif /* !(_SPARC64_HEAD_H) */
diff --git a/arch/sparc/include/asm/hibernate.h b/arch/sparc/include/asm/hibernate.h
new file mode 100644
index 00000000000..2ec34f84224
--- /dev/null
+++ b/arch/sparc/include/asm/hibernate.h
@@ -0,0 +1,23 @@
+/*
+ * hibernate.h: Hibernaton support specific for sparc64.
+ *
+ * Copyright (C) 2013 Kirill V Tkhai (tkhai@yandex.ru)
+ */
+
+#ifndef ___SPARC_HIBERNATE_H
+#define ___SPARC_HIBERNATE_H
+
+struct saved_context {
+ unsigned long fp;
+ unsigned long cwp;
+ unsigned long wstate;
+
+ unsigned long tick;
+ unsigned long pstate;
+
+ unsigned long g4;
+ unsigned long g5;
+ unsigned long g6;
+};
+
+#endif
diff --git a/arch/sparc/include/asm/highmem.h b/arch/sparc/include/asm/highmem.h
new file mode 100644
index 00000000000..92ded294a4e
--- /dev/null
+++ b/arch/sparc/include/asm/highmem.h
@@ -0,0 +1,78 @@
+/*
+ * highmem.h: virtual kernel memory mappings for high memory
+ *
+ * Used in CONFIG_HIGHMEM systems for memory pages which
+ * are not addressable by direct kernel virtual addresses.
+ *
+ * Copyright (C) 1999 Gerhard Wichert, Siemens AG
+ * Gerhard.Wichert@pdb.siemens.de
+ *
+ *
+ * Redesigned the x86 32-bit VM architecture to deal with
+ * up to 16 Terrabyte physical memory. With current x86 CPUs
+ * we now support up to 64 Gigabytes physical RAM.
+ *
+ * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
+ */
+
+#ifndef _ASM_HIGHMEM_H
+#define _ASM_HIGHMEM_H
+
+#ifdef __KERNEL__
+
+#include <linux/interrupt.h>
+#include <asm/vaddrs.h>
+#include <asm/kmap_types.h>
+#include <asm/pgtable.h>
+
+/* declarations for highmem.c */
+extern unsigned long highstart_pfn, highend_pfn;
+
+extern pgprot_t kmap_prot;
+extern pte_t *pkmap_page_table;
+
+void kmap_init(void) __init;
+
+/*
+ * Right now we initialize only a single pte table. It can be extended
+ * easily, subsequent pte tables have to be allocated in one physical
+ * chunk of RAM. Currently the simplest way to do this is to align the
+ * pkmap region on a pagetable boundary (4MB).
+ */
+#define LAST_PKMAP 1024
+#define PKMAP_SIZE (LAST_PKMAP << PAGE_SHIFT)
+#define PKMAP_BASE PMD_ALIGN(SRMMU_NOCACHE_VADDR + (SRMMU_MAX_NOCACHE_PAGES << PAGE_SHIFT))
+
+#define LAST_PKMAP_MASK (LAST_PKMAP - 1)
+#define PKMAP_NR(virt) ((virt - PKMAP_BASE) >> PAGE_SHIFT)
+#define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT))
+
+#define PKMAP_END (PKMAP_ADDR(LAST_PKMAP))
+
+void *kmap_high(struct page *page);
+void kunmap_high(struct page *page);
+
+static inline void *kmap(struct page *page)
+{
+ BUG_ON(in_interrupt());
+ if (!PageHighMem(page))
+ return page_address(page);
+ return kmap_high(page);
+}
+
+static inline void kunmap(struct page *page)
+{
+ BUG_ON(in_interrupt());
+ if (!PageHighMem(page))
+ return;
+ kunmap_high(page);
+}
+
+void *kmap_atomic(struct page *page);
+void __kunmap_atomic(void *kvaddr);
+
+#define flush_cache_kmaps() flush_cache_all()
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_HIGHMEM_H */
diff --git a/arch/sparc/include/asm/hugetlb.h b/arch/sparc/include/asm/hugetlb.h
new file mode 100644
index 00000000000..e4cab465b81
--- /dev/null
+++ b/arch/sparc/include/asm/hugetlb.h
@@ -0,0 +1,98 @@
+#ifndef _ASM_SPARC64_HUGETLB_H
+#define _ASM_SPARC64_HUGETLB_H
+
+#include <asm/page.h>
+#include <asm-generic/hugetlb.h>
+
+
+void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t pte);
+
+pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep);
+
+static inline void hugetlb_prefault_arch_hook(struct mm_struct *mm)
+{
+}
+
+static inline int is_hugepage_only_range(struct mm_struct *mm,
+ unsigned long addr,
+ unsigned long len) {
+ return 0;
+}
+
+/*
+ * If the arch doesn't supply something else, assume that hugepage
+ * size aligned regions are ok without further preparation.
+ */
+static inline int prepare_hugepage_range(struct file *file,
+ unsigned long addr, unsigned long len)
+{
+ if (len & ~HPAGE_MASK)
+ return -EINVAL;
+ if (addr & ~HPAGE_MASK)
+ return -EINVAL;
+ return 0;
+}
+
+static inline void hugetlb_free_pgd_range(struct mmu_gather *tlb,
+ unsigned long addr, unsigned long end,
+ unsigned long floor,
+ unsigned long ceiling)
+{
+ free_pgd_range(tlb, addr, end, floor, ceiling);
+}
+
+static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
+ unsigned long addr, pte_t *ptep)
+{
+}
+
+static inline int huge_pte_none(pte_t pte)
+{
+ return pte_none(pte);
+}
+
+static inline pte_t huge_pte_wrprotect(pte_t pte)
+{
+ return pte_wrprotect(pte);
+}
+
+static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
+ unsigned long addr, pte_t *ptep)
+{
+ pte_t old_pte = *ptep;
+ set_huge_pte_at(mm, addr, ptep, pte_wrprotect(old_pte));
+}
+
+static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
+ unsigned long addr, pte_t *ptep,
+ pte_t pte, int dirty)
+{
+ int changed = !pte_same(*ptep, pte);
+ if (changed) {
+ set_huge_pte_at(vma->vm_mm, addr, ptep, pte);
+ flush_tlb_page(vma, addr);
+ }
+ return changed;
+}
+
+static inline pte_t huge_ptep_get(pte_t *ptep)
+{
+ return *ptep;
+}
+
+static inline int arch_prepare_hugepage(struct page *page)
+{
+ return 0;
+}
+
+static inline void arch_release_hugepage(struct page *page)
+{
+}
+
+static inline void arch_clear_hugepage_flags(struct page *page)
+{
+}
+
+#endif /* _ASM_SPARC64_HUGETLB_H */
diff --git a/arch/sparc/include/asm/hvtramp.h b/arch/sparc/include/asm/hvtramp.h
new file mode 100644
index 00000000000..04b56f862bb
--- /dev/null
+++ b/arch/sparc/include/asm/hvtramp.h
@@ -0,0 +1,37 @@
+#ifndef _SPARC64_HVTRAP_H
+#define _SPARC64_HVTRAP_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+struct hvtramp_mapping {
+ __u64 vaddr;
+ __u64 tte;
+};
+
+struct hvtramp_descr {
+ __u32 cpu;
+ __u32 num_mappings;
+ __u64 fault_info_va;
+ __u64 fault_info_pa;
+ __u64 thread_reg;
+ struct hvtramp_mapping maps[1];
+};
+
+void hv_cpu_startup(unsigned long hvdescr_pa);
+
+#endif
+
+#define HVTRAMP_DESCR_CPU 0x00
+#define HVTRAMP_DESCR_NUM_MAPPINGS 0x04
+#define HVTRAMP_DESCR_FAULT_INFO_VA 0x08
+#define HVTRAMP_DESCR_FAULT_INFO_PA 0x10
+#define HVTRAMP_DESCR_THREAD_REG 0x18
+#define HVTRAMP_DESCR_MAPS 0x20
+
+#define HVTRAMP_MAPPING_VADDR 0x00
+#define HVTRAMP_MAPPING_TTE 0x08
+#define HVTRAMP_MAPPING_SIZE 0x10
+
+#endif /* _SPARC64_HVTRAP_H */
diff --git a/arch/sparc/include/asm/hw_irq.h b/arch/sparc/include/asm/hw_irq.h
new file mode 100644
index 00000000000..8d30a7694be
--- /dev/null
+++ b/arch/sparc/include/asm/hw_irq.h
@@ -0,0 +1,6 @@
+#ifndef __ASM_SPARC_HW_IRQ_H
+#define __ASM_SPARC_HW_IRQ_H
+
+/* Dummy include. */
+
+#endif
diff --git a/arch/sparc/include/asm/hypervisor.h b/arch/sparc/include/asm/hypervisor.h
new file mode 100644
index 00000000000..94b39caea3e
--- /dev/null
+++ b/arch/sparc/include/asm/hypervisor.h
@@ -0,0 +1,3001 @@
+#ifndef _SPARC64_HYPERVISOR_H
+#define _SPARC64_HYPERVISOR_H
+
+/* Sun4v hypervisor interfaces and defines.
+ *
+ * Hypervisor calls are made via traps to software traps number 0x80
+ * and above. Registers %o0 to %o5 serve as argument, status, and
+ * return value registers.
+ *
+ * There are two kinds of these traps. First there are the normal
+ * "fast traps" which use software trap 0x80 and encode the function
+ * to invoke by number in register %o5. Argument and return value
+ * handling is as follows:
+ *
+ * -----------------------------------------------
+ * | %o5 | function number | undefined |
+ * | %o0 | argument 0 | return status |
+ * | %o1 | argument 1 | return value 1 |
+ * | %o2 | argument 2 | return value 2 |
+ * | %o3 | argument 3 | return value 3 |
+ * | %o4 | argument 4 | return value 4 |
+ * -----------------------------------------------
+ *
+ * The second type are "hyper-fast traps" which encode the function
+ * number in the software trap number itself. So these use trap
+ * numbers > 0x80. The register usage for hyper-fast traps is as
+ * follows:
+ *
+ * -----------------------------------------------
+ * | %o0 | argument 0 | return status |
+ * | %o1 | argument 1 | return value 1 |
+ * | %o2 | argument 2 | return value 2 |
+ * | %o3 | argument 3 | return value 3 |
+ * | %o4 | argument 4 | return value 4 |
+ * -----------------------------------------------
+ *
+ * Registers providing explicit arguments to the hypervisor calls
+ * are volatile across the call. Upon return their values are
+ * undefined unless explicitly specified as containing a particular
+ * return value by the specific call. The return status is always
+ * returned in register %o0, zero indicates a successful execution of
+ * the hypervisor call and other values indicate an error status as
+ * defined below. So, for example, if a hyper-fast trap takes
+ * arguments 0, 1, and 2, then %o0, %o1, and %o2 are volatile across
+ * the call and %o3, %o4, and %o5 would be preserved.
+ *
+ * If the hypervisor trap is invalid, or the fast trap function number
+ * is invalid, HV_EBADTRAP will be returned in %o0. Also, all 64-bits
+ * of the argument and return values are significant.
+ */
+
+/* Trap numbers. */
+#define HV_FAST_TRAP 0x80
+#define HV_MMU_MAP_ADDR_TRAP 0x83
+#define HV_MMU_UNMAP_ADDR_TRAP 0x84
+#define HV_TTRACE_ADDENTRY_TRAP 0x85
+#define HV_CORE_TRAP 0xff
+
+/* Error codes. */
+#define HV_EOK 0 /* Successful return */
+#define HV_ENOCPU 1 /* Invalid CPU id */
+#define HV_ENORADDR 2 /* Invalid real address */
+#define HV_ENOINTR 3 /* Invalid interrupt id */
+#define HV_EBADPGSZ 4 /* Invalid pagesize encoding */
+#define HV_EBADTSB 5 /* Invalid TSB description */
+#define HV_EINVAL 6 /* Invalid argument */
+#define HV_EBADTRAP 7 /* Invalid function number */
+#define HV_EBADALIGN 8 /* Invalid address alignment */
+#define HV_EWOULDBLOCK 9 /* Cannot complete w/o blocking */
+#define HV_ENOACCESS 10 /* No access to resource */
+#define HV_EIO 11 /* I/O error */
+#define HV_ECPUERROR 12 /* CPU in error state */
+#define HV_ENOTSUPPORTED 13 /* Function not supported */
+#define HV_ENOMAP 14 /* No mapping found */
+#define HV_ETOOMANY 15 /* Too many items specified */
+#define HV_ECHANNEL 16 /* Invalid LDC channel */
+#define HV_EBUSY 17 /* Resource busy */
+
+/* mach_exit()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MACH_EXIT
+ * ARG0: exit code
+ * ERRORS: This service does not return.
+ *
+ * Stop all CPUs in the virtual domain and place them into the stopped
+ * state. The 64-bit exit code may be passed to a service entity as
+ * the domain's exit status. On systems without a service entity, the
+ * domain will undergo a reset, and the boot firmware will be
+ * reloaded.
+ *
+ * This function will never return to the guest that invokes it.
+ *
+ * Note: By convention an exit code of zero denotes a successful exit by
+ * the guest code. A non-zero exit code denotes a guest specific
+ * error indication.
+ *
+ */
+#define HV_FAST_MACH_EXIT 0x00
+
+#ifndef __ASSEMBLY__
+void sun4v_mach_exit(unsigned long exit_code);
+#endif
+
+/* Domain services. */
+
+/* mach_desc()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MACH_DESC
+ * ARG0: buffer
+ * ARG1: length
+ * RET0: status
+ * RET1: length
+ * ERRORS: HV_EBADALIGN Buffer is badly aligned
+ * HV_ENORADDR Buffer is to an illegal real address.
+ * HV_EINVAL Buffer length is too small for complete
+ * machine description.
+ *
+ * Copy the most current machine description into the buffer indicated
+ * by the real address in ARG0. The buffer provided must be 16 byte
+ * aligned. Upon success or HV_EINVAL, this service returns the
+ * actual size of the machine description in the RET1 return value.
+ *
+ * Note: A method of determining the appropriate buffer size for the
+ * machine description is to first call this service with a buffer
+ * length of 0 bytes.
+ */
+#define HV_FAST_MACH_DESC 0x01
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_mach_desc(unsigned long buffer_pa,
+ unsigned long buf_len,
+ unsigned long *real_buf_len);
+#endif
+
+/* mach_sir()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MACH_SIR
+ * ERRORS: This service does not return.
+ *
+ * Perform a software initiated reset of the virtual machine domain.
+ * All CPUs are captured as soon as possible, all hardware devices are
+ * returned to the entry default state, and the domain is restarted at
+ * the SIR (trap type 0x04) real trap table (RTBA) entry point on one
+ * of the CPUs. The single CPU restarted is selected as determined by
+ * platform specific policy. Memory is preserved across this
+ * operation.
+ */
+#define HV_FAST_MACH_SIR 0x02
+
+#ifndef __ASSEMBLY__
+void sun4v_mach_sir(void);
+#endif
+
+/* mach_set_watchdog()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MACH_SET_WATCHDOG
+ * ARG0: timeout in milliseconds
+ * RET0: status
+ * RET1: time remaining in milliseconds
+ *
+ * A guest uses this API to set a watchdog timer. Once the gues has set
+ * the timer, it must call the timer service again either to disable or
+ * postpone the expiration. If the timer expires before being reset or
+ * disabled, then the hypervisor take a platform specific action leading
+ * to guest termination within a bounded time period. The platform action
+ * may include recovery actions such as reporting the expiration to a
+ * Service Processor, and/or automatically restarting the gues.
+ *
+ * The 'timeout' parameter is specified in milliseconds, however the
+ * implementated granularity is given by the 'watchdog-resolution'
+ * property in the 'platform' node of the guest's machine description.
+ * The largest allowed timeout value is specified by the
+ * 'watchdog-max-timeout' property of the 'platform' node.
+ *
+ * If the 'timeout' argument is not zero, the watchdog timer is set to
+ * expire after a minimum of 'timeout' milliseconds.
+ *
+ * If the 'timeout' argument is zero, the watchdog timer is disabled.
+ *
+ * If the 'timeout' value exceeds the value of the 'max-watchdog-timeout'
+ * property, the hypervisor leaves the watchdog timer state unchanged,
+ * and returns a status of EINVAL.
+ *
+ * The 'time remaining' return value is valid regardless of whether the
+ * return status is EOK or EINVAL. A non-zero return value indicates the
+ * number of milliseconds that were remaining until the timer was to expire.
+ * If less than one millisecond remains, the return value is '1'. If the
+ * watchdog timer was disabled at the time of the call, the return value is
+ * zero.
+ *
+ * If the hypervisor cannot support the exact timeout value requested, but
+ * can support a larger timeout value, the hypervisor may round the actual
+ * timeout to a value larger than the requested timeout, consequently the
+ * 'time remaining' return value may be larger than the previously requested
+ * timeout value.
+ *
+ * Any guest OS debugger should be aware that the watchdog service may be in
+ * use. Consequently, it is recommended that the watchdog service is
+ * disabled upon debugger entry (e.g. reaching a breakpoint), and then
+ * re-enabled upon returning to normal execution. The API has been designed
+ * with this in mind, and the 'time remaining' result of the disable call may
+ * be used directly as the timeout argument of the re-enable call.
+ */
+#define HV_FAST_MACH_SET_WATCHDOG 0x05
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_mach_set_watchdog(unsigned long timeout,
+ unsigned long *orig_timeout);
+#endif
+
+/* CPU services.
+ *
+ * CPUs represent devices that can execute software threads. A single
+ * chip that contains multiple cores or strands is represented as
+ * multiple CPUs with unique CPU identifiers. CPUs are exported to
+ * OBP via the machine description (and to the OS via the OBP device
+ * tree). CPUs are always in one of three states: stopped, running,
+ * or error.
+ *
+ * A CPU ID is a pre-assigned 16-bit value that uniquely identifies a
+ * CPU within a logical domain. Operations that are to be performed
+ * on multiple CPUs specify them via a CPU list. A CPU list is an
+ * array in real memory, of which each 16-bit word is a CPU ID. CPU
+ * lists are passed through the API as two arguments. The first is
+ * the number of entries (16-bit words) in the CPU list, and the
+ * second is the (real address) pointer to the CPU ID list.
+ */
+
+/* cpu_start()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_CPU_START
+ * ARG0: CPU ID
+ * ARG1: PC
+ * ARG2: RTBA
+ * ARG3: target ARG0
+ * RET0: status
+ * ERRORS: ENOCPU Invalid CPU ID
+ * EINVAL Target CPU ID is not in the stopped state
+ * ENORADDR Invalid PC or RTBA real address
+ * EBADALIGN Unaligned PC or unaligned RTBA
+ * EWOULDBLOCK Starting resources are not available
+ *
+ * Start CPU with given CPU ID with PC in %pc and with a real trap
+ * base address value of RTBA. The indicated CPU must be in the
+ * stopped state. The supplied RTBA must be aligned on a 256 byte
+ * boundary. On successful completion, the specified CPU will be in
+ * the running state and will be supplied with "target ARG0" in %o0
+ * and RTBA in %tba.
+ */
+#define HV_FAST_CPU_START 0x10
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_cpu_start(unsigned long cpuid,
+ unsigned long pc,
+ unsigned long rtba,
+ unsigned long arg0);
+#endif
+
+/* cpu_stop()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_CPU_STOP
+ * ARG0: CPU ID
+ * RET0: status
+ * ERRORS: ENOCPU Invalid CPU ID
+ * EINVAL Target CPU ID is the current cpu
+ * EINVAL Target CPU ID is not in the running state
+ * EWOULDBLOCK Stopping resources are not available
+ * ENOTSUPPORTED Not supported on this platform
+ *
+ * The specified CPU is stopped. The indicated CPU must be in the
+ * running state. On completion, it will be in the stopped state. It
+ * is not legal to stop the current CPU.
+ *
+ * Note: As this service cannot be used to stop the current cpu, this service
+ * may not be used to stop the last running CPU in a domain. To stop
+ * and exit a running domain, a guest must use the mach_exit() service.
+ */
+#define HV_FAST_CPU_STOP 0x11
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_cpu_stop(unsigned long cpuid);
+#endif
+
+/* cpu_yield()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_CPU_YIELD
+ * RET0: status
+ * ERRORS: No possible error.
+ *
+ * Suspend execution on the current CPU. Execution will resume when
+ * an interrupt (device, %stick_compare, or cross-call) is targeted to
+ * the CPU. On some CPUs, this API may be used by the hypervisor to
+ * save power by disabling hardware strands.
+ */
+#define HV_FAST_CPU_YIELD 0x12
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_cpu_yield(void);
+#endif
+
+/* cpu_qconf()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_CPU_QCONF
+ * ARG0: queue
+ * ARG1: base real address
+ * ARG2: number of entries
+ * RET0: status
+ * ERRORS: ENORADDR Invalid base real address
+ * EINVAL Invalid queue or number of entries is less
+ * than 2 or too large.
+ * EBADALIGN Base real address is not correctly aligned
+ * for size.
+ *
+ * Configure the given queue to be placed at the given base real
+ * address, with the given number of entries. The number of entries
+ * must be a power of 2. The base real address must be aligned
+ * exactly to match the queue size. Each queue entry is 64 bytes
+ * long, so for example a 32 entry queue must be aligned on a 2048
+ * byte real address boundary.
+ *
+ * The specified queue is unconfigured if the number of entries is given
+ * as zero.
+ *
+ * For the current version of this API service, the argument queue is defined
+ * as follows:
+ *
+ * queue description
+ * ----- -------------------------
+ * 0x3c cpu mondo queue
+ * 0x3d device mondo queue
+ * 0x3e resumable error queue
+ * 0x3f non-resumable error queue
+ *
+ * Note: The maximum number of entries for each queue for a specific cpu may
+ * be determined from the machine description.
+ */
+#define HV_FAST_CPU_QCONF 0x14
+#define HV_CPU_QUEUE_CPU_MONDO 0x3c
+#define HV_CPU_QUEUE_DEVICE_MONDO 0x3d
+#define HV_CPU_QUEUE_RES_ERROR 0x3e
+#define HV_CPU_QUEUE_NONRES_ERROR 0x3f
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_cpu_qconf(unsigned long type,
+ unsigned long queue_paddr,
+ unsigned long num_queue_entries);
+#endif
+
+/* cpu_qinfo()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_CPU_QINFO
+ * ARG0: queue
+ * RET0: status
+ * RET1: base real address
+ * RET1: number of entries
+ * ERRORS: EINVAL Invalid queue
+ *
+ * Return the configuration info for the given queue. The base real
+ * address and number of entries of the defined queue are returned.
+ * The queue argument values are the same as for cpu_qconf() above.
+ *
+ * If the specified queue is a valid queue number, but no queue has
+ * been defined, the number of entries will be set to zero and the
+ * base real address returned is undefined.
+ */
+#define HV_FAST_CPU_QINFO 0x15
+
+/* cpu_mondo_send()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_CPU_MONDO_SEND
+ * ARG0-1: CPU list
+ * ARG2: data real address
+ * RET0: status
+ * ERRORS: EBADALIGN Mondo data is not 64-byte aligned or CPU list
+ * is not 2-byte aligned.
+ * ENORADDR Invalid data mondo address, or invalid cpu list
+ * address.
+ * ENOCPU Invalid cpu in CPU list
+ * EWOULDBLOCK Some or all of the listed CPUs did not receive
+ * the mondo
+ * ECPUERROR One or more of the listed CPUs are in error
+ * state, use HV_FAST_CPU_STATE to see which ones
+ * EINVAL CPU list includes caller's CPU ID
+ *
+ * Send a mondo interrupt to the CPUs in the given CPU list with the
+ * 64-bytes at the given data real address. The data must be 64-byte
+ * aligned. The mondo data will be delivered to the cpu_mondo queues
+ * of the recipient CPUs.
+ *
+ * In all cases, error or not, the CPUs in the CPU list to which the
+ * mondo has been successfully delivered will be indicated by having
+ * their entry in CPU list updated with the value 0xffff.
+ */
+#define HV_FAST_CPU_MONDO_SEND 0x42
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_cpu_mondo_send(unsigned long cpu_count,
+ unsigned long cpu_list_pa,
+ unsigned long mondo_block_pa);
+#endif
+
+/* cpu_myid()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_CPU_MYID
+ * RET0: status
+ * RET1: CPU ID
+ * ERRORS: No errors defined.
+ *
+ * Return the hypervisor ID handle for the current CPU. Use by a
+ * virtual CPU to discover it's own identity.
+ */
+#define HV_FAST_CPU_MYID 0x16
+
+/* cpu_state()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_CPU_STATE
+ * ARG0: CPU ID
+ * RET0: status
+ * RET1: state
+ * ERRORS: ENOCPU Invalid CPU ID
+ *
+ * Retrieve the current state of the CPU with the given CPU ID.
+ */
+#define HV_FAST_CPU_STATE 0x17
+#define HV_CPU_STATE_STOPPED 0x01
+#define HV_CPU_STATE_RUNNING 0x02
+#define HV_CPU_STATE_ERROR 0x03
+
+#ifndef __ASSEMBLY__
+long sun4v_cpu_state(unsigned long cpuid);
+#endif
+
+/* cpu_set_rtba()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_CPU_SET_RTBA
+ * ARG0: RTBA
+ * RET0: status
+ * RET1: previous RTBA
+ * ERRORS: ENORADDR Invalid RTBA real address
+ * EBADALIGN RTBA is incorrectly aligned for a trap table
+ *
+ * Set the real trap base address of the local cpu to the given RTBA.
+ * The supplied RTBA must be aligned on a 256 byte boundary. Upon
+ * success the previous value of the RTBA is returned in RET1.
+ *
+ * Note: This service does not affect %tba
+ */
+#define HV_FAST_CPU_SET_RTBA 0x18
+
+/* cpu_set_rtba()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_CPU_GET_RTBA
+ * RET0: status
+ * RET1: previous RTBA
+ * ERRORS: No possible error.
+ *
+ * Returns the current value of RTBA in RET1.
+ */
+#define HV_FAST_CPU_GET_RTBA 0x19
+
+/* MMU services.
+ *
+ * Layout of a TSB description for mmu_tsb_ctx{,non}0() calls.
+ */
+#ifndef __ASSEMBLY__
+struct hv_tsb_descr {
+ unsigned short pgsz_idx;
+ unsigned short assoc;
+ unsigned int num_ttes; /* in TTEs */
+ unsigned int ctx_idx;
+ unsigned int pgsz_mask;
+ unsigned long tsb_base;
+ unsigned long resv;
+};
+#endif
+#define HV_TSB_DESCR_PGSZ_IDX_OFFSET 0x00
+#define HV_TSB_DESCR_ASSOC_OFFSET 0x02
+#define HV_TSB_DESCR_NUM_TTES_OFFSET 0x04
+#define HV_TSB_DESCR_CTX_IDX_OFFSET 0x08
+#define HV_TSB_DESCR_PGSZ_MASK_OFFSET 0x0c
+#define HV_TSB_DESCR_TSB_BASE_OFFSET 0x10
+#define HV_TSB_DESCR_RESV_OFFSET 0x18
+
+/* Page size bitmask. */
+#define HV_PGSZ_MASK_8K (1 << 0)
+#define HV_PGSZ_MASK_64K (1 << 1)
+#define HV_PGSZ_MASK_512K (1 << 2)
+#define HV_PGSZ_MASK_4MB (1 << 3)
+#define HV_PGSZ_MASK_32MB (1 << 4)
+#define HV_PGSZ_MASK_256MB (1 << 5)
+#define HV_PGSZ_MASK_2GB (1 << 6)
+#define HV_PGSZ_MASK_16GB (1 << 7)
+
+/* Page size index. The value given in the TSB descriptor must correspond
+ * to the smallest page size specified in the pgsz_mask page size bitmask.
+ */
+#define HV_PGSZ_IDX_8K 0
+#define HV_PGSZ_IDX_64K 1
+#define HV_PGSZ_IDX_512K 2
+#define HV_PGSZ_IDX_4MB 3
+#define HV_PGSZ_IDX_32MB 4
+#define HV_PGSZ_IDX_256MB 5
+#define HV_PGSZ_IDX_2GB 6
+#define HV_PGSZ_IDX_16GB 7
+
+/* MMU fault status area.
+ *
+ * MMU related faults have their status and fault address information
+ * placed into a memory region made available by privileged code. Each
+ * virtual processor must make a mmu_fault_area_conf() call to tell the
+ * hypervisor where that processor's fault status should be stored.
+ *
+ * The fault status block is a multiple of 64-bytes and must be aligned
+ * on a 64-byte boundary.
+ */
+#ifndef __ASSEMBLY__
+struct hv_fault_status {
+ unsigned long i_fault_type;
+ unsigned long i_fault_addr;
+ unsigned long i_fault_ctx;
+ unsigned long i_reserved[5];
+ unsigned long d_fault_type;
+ unsigned long d_fault_addr;
+ unsigned long d_fault_ctx;
+ unsigned long d_reserved[5];
+};
+#endif
+#define HV_FAULT_I_TYPE_OFFSET 0x00
+#define HV_FAULT_I_ADDR_OFFSET 0x08
+#define HV_FAULT_I_CTX_OFFSET 0x10
+#define HV_FAULT_D_TYPE_OFFSET 0x40
+#define HV_FAULT_D_ADDR_OFFSET 0x48
+#define HV_FAULT_D_CTX_OFFSET 0x50
+
+#define HV_FAULT_TYPE_FAST_MISS 1
+#define HV_FAULT_TYPE_FAST_PROT 2
+#define HV_FAULT_TYPE_MMU_MISS 3
+#define HV_FAULT_TYPE_INV_RA 4
+#define HV_FAULT_TYPE_PRIV_VIOL 5
+#define HV_FAULT_TYPE_PROT_VIOL 6
+#define HV_FAULT_TYPE_NFO 7
+#define HV_FAULT_TYPE_NFO_SEFF 8
+#define HV_FAULT_TYPE_INV_VA 9
+#define HV_FAULT_TYPE_INV_ASI 10
+#define HV_FAULT_TYPE_NC_ATOMIC 11
+#define HV_FAULT_TYPE_PRIV_ACT 12
+#define HV_FAULT_TYPE_RESV1 13
+#define HV_FAULT_TYPE_UNALIGNED 14
+#define HV_FAULT_TYPE_INV_PGSZ 15
+/* Values 16 --> -2 are reserved. */
+#define HV_FAULT_TYPE_MULTIPLE -1
+
+/* Flags argument for mmu_{map,unmap}_addr(), mmu_demap_{page,context,all}(),
+ * and mmu_{map,unmap}_perm_addr().
+ */
+#define HV_MMU_DMMU 0x01
+#define HV_MMU_IMMU 0x02
+#define HV_MMU_ALL (HV_MMU_DMMU | HV_MMU_IMMU)
+
+/* mmu_map_addr()
+ * TRAP: HV_MMU_MAP_ADDR_TRAP
+ * ARG0: virtual address
+ * ARG1: mmu context
+ * ARG2: TTE
+ * ARG3: flags (HV_MMU_{IMMU,DMMU})
+ * ERRORS: EINVAL Invalid virtual address, mmu context, or flags
+ * EBADPGSZ Invalid page size value
+ * ENORADDR Invalid real address in TTE
+ *
+ * Create a non-permanent mapping using the given TTE, virtual
+ * address, and mmu context. The flags argument determines which
+ * (data, or instruction, or both) TLB the mapping gets loaded into.
+ *
+ * The behavior is undefined if the valid bit is clear in the TTE.
+ *
+ * Note: This API call is for privileged code to specify temporary translation
+ * mappings without the need to create and manage a TSB.
+ */
+
+/* mmu_unmap_addr()
+ * TRAP: HV_MMU_UNMAP_ADDR_TRAP
+ * ARG0: virtual address
+ * ARG1: mmu context
+ * ARG2: flags (HV_MMU_{IMMU,DMMU})
+ * ERRORS: EINVAL Invalid virtual address, mmu context, or flags
+ *
+ * Demaps the given virtual address in the given mmu context on this
+ * CPU. This function is intended to be used to demap pages mapped
+ * with mmu_map_addr. This service is equivalent to invoking
+ * mmu_demap_page() with only the current CPU in the CPU list. The
+ * flags argument determines which (data, or instruction, or both) TLB
+ * the mapping gets unmapped from.
+ *
+ * Attempting to perform an unmap operation for a previously defined
+ * permanent mapping will have undefined results.
+ */
+
+/* mmu_tsb_ctx0()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MMU_TSB_CTX0
+ * ARG0: number of TSB descriptions
+ * ARG1: TSB descriptions pointer
+ * RET0: status
+ * ERRORS: ENORADDR Invalid TSB descriptions pointer or
+ * TSB base within a descriptor
+ * EBADALIGN TSB descriptions pointer is not aligned
+ * to an 8-byte boundary, or TSB base
+ * within a descriptor is not aligned for
+ * the given TSB size
+ * EBADPGSZ Invalid page size in a TSB descriptor
+ * EBADTSB Invalid associativity or size in a TSB
+ * descriptor
+ * EINVAL Invalid number of TSB descriptions, or
+ * invalid context index in a TSB
+ * descriptor, or index page size not
+ * equal to smallest page size in page
+ * size bitmask field.
+ *
+ * Configures the TSBs for the current CPU for virtual addresses with
+ * context zero. The TSB descriptions pointer is a pointer to an
+ * array of the given number of TSB descriptions.
+ *
+ * Note: The maximum number of TSBs available to a virtual CPU is given by the
+ * mmu-max-#tsbs property of the cpu's corresponding "cpu" node in the
+ * machine description.
+ */
+#define HV_FAST_MMU_TSB_CTX0 0x20
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_mmu_tsb_ctx0(unsigned long num_descriptions,
+ unsigned long tsb_desc_ra);
+#endif
+
+/* mmu_tsb_ctxnon0()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MMU_TSB_CTXNON0
+ * ARG0: number of TSB descriptions
+ * ARG1: TSB descriptions pointer
+ * RET0: status
+ * ERRORS: Same as for mmu_tsb_ctx0() above.
+ *
+ * Configures the TSBs for the current CPU for virtual addresses with
+ * non-zero contexts. The TSB descriptions pointer is a pointer to an
+ * array of the given number of TSB descriptions.
+ *
+ * Note: A maximum of 16 TSBs may be specified in the TSB description list.
+ */
+#define HV_FAST_MMU_TSB_CTXNON0 0x21
+
+/* mmu_demap_page()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MMU_DEMAP_PAGE
+ * ARG0: reserved, must be zero
+ * ARG1: reserved, must be zero
+ * ARG2: virtual address
+ * ARG3: mmu context
+ * ARG4: flags (HV_MMU_{IMMU,DMMU})
+ * RET0: status
+ * ERRORS: EINVAL Invalid virtual address, context, or
+ * flags value
+ * ENOTSUPPORTED ARG0 or ARG1 is non-zero
+ *
+ * Demaps any page mapping of the given virtual address in the given
+ * mmu context for the current virtual CPU. Any virtually tagged
+ * caches are guaranteed to be kept consistent. The flags argument
+ * determines which TLB (instruction, or data, or both) participate in
+ * the operation.
+ *
+ * ARG0 and ARG1 are both reserved and must be set to zero.
+ */
+#define HV_FAST_MMU_DEMAP_PAGE 0x22
+
+/* mmu_demap_ctx()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MMU_DEMAP_CTX
+ * ARG0: reserved, must be zero
+ * ARG1: reserved, must be zero
+ * ARG2: mmu context
+ * ARG3: flags (HV_MMU_{IMMU,DMMU})
+ * RET0: status
+ * ERRORS: EINVAL Invalid context or flags value
+ * ENOTSUPPORTED ARG0 or ARG1 is non-zero
+ *
+ * Demaps all non-permanent virtual page mappings previously specified
+ * for the given context for the current virtual CPU. Any virtual
+ * tagged caches are guaranteed to be kept consistent. The flags
+ * argument determines which TLB (instruction, or data, or both)
+ * participate in the operation.
+ *
+ * ARG0 and ARG1 are both reserved and must be set to zero.
+ */
+#define HV_FAST_MMU_DEMAP_CTX 0x23
+
+/* mmu_demap_all()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MMU_DEMAP_ALL
+ * ARG0: reserved, must be zero
+ * ARG1: reserved, must be zero
+ * ARG2: flags (HV_MMU_{IMMU,DMMU})
+ * RET0: status
+ * ERRORS: EINVAL Invalid flags value
+ * ENOTSUPPORTED ARG0 or ARG1 is non-zero
+ *
+ * Demaps all non-permanent virtual page mappings previously specified
+ * for the current virtual CPU. Any virtual tagged caches are
+ * guaranteed to be kept consistent. The flags argument determines
+ * which TLB (instruction, or data, or both) participate in the
+ * operation.
+ *
+ * ARG0 and ARG1 are both reserved and must be set to zero.
+ */
+#define HV_FAST_MMU_DEMAP_ALL 0x24
+
+#ifndef __ASSEMBLY__
+void sun4v_mmu_demap_all(void);
+#endif
+
+/* mmu_map_perm_addr()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MMU_MAP_PERM_ADDR
+ * ARG0: virtual address
+ * ARG1: reserved, must be zero
+ * ARG2: TTE
+ * ARG3: flags (HV_MMU_{IMMU,DMMU})
+ * RET0: status
+ * ERRORS: EINVAL Invalid virtual address or flags value
+ * EBADPGSZ Invalid page size value
+ * ENORADDR Invalid real address in TTE
+ * ETOOMANY Too many mappings (max of 8 reached)
+ *
+ * Create a permanent mapping using the given TTE and virtual address
+ * for context 0 on the calling virtual CPU. A maximum of 8 such
+ * permanent mappings may be specified by privileged code. Mappings
+ * may be removed with mmu_unmap_perm_addr().
+ *
+ * The behavior is undefined if a TTE with the valid bit clear is given.
+ *
+ * Note: This call is used to specify address space mappings for which
+ * privileged code does not expect to receive misses. For example,
+ * this mechanism can be used to map kernel nucleus code and data.
+ */
+#define HV_FAST_MMU_MAP_PERM_ADDR 0x25
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_mmu_map_perm_addr(unsigned long vaddr,
+ unsigned long set_to_zero,
+ unsigned long tte,
+ unsigned long flags);
+#endif
+
+/* mmu_fault_area_conf()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MMU_FAULT_AREA_CONF
+ * ARG0: real address
+ * RET0: status
+ * RET1: previous mmu fault area real address
+ * ERRORS: ENORADDR Invalid real address
+ * EBADALIGN Invalid alignment for fault area
+ *
+ * Configure the MMU fault status area for the calling CPU. A 64-byte
+ * aligned real address specifies where MMU fault status information
+ * is placed. The return value is the previously specified area, or 0
+ * for the first invocation. Specifying a fault area at real address
+ * 0 is not allowed.
+ */
+#define HV_FAST_MMU_FAULT_AREA_CONF 0x26
+
+/* mmu_enable()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MMU_ENABLE
+ * ARG0: enable flag
+ * ARG1: return target address
+ * RET0: status
+ * ERRORS: ENORADDR Invalid real address when disabling
+ * translation.
+ * EBADALIGN The return target address is not
+ * aligned to an instruction.
+ * EINVAL The enable flag request the current
+ * operating mode (e.g. disable if already
+ * disabled)
+ *
+ * Enable or disable virtual address translation for the calling CPU
+ * within the virtual machine domain. If the enable flag is zero,
+ * translation is disabled, any non-zero value will enable
+ * translation.
+ *
+ * When this function returns, the newly selected translation mode
+ * will be active. If the mmu is being enabled, then the return
+ * target address is a virtual address else it is a real address.
+ *
+ * Upon successful completion, control will be returned to the given
+ * return target address (ie. the cpu will jump to that address). On
+ * failure, the previous mmu mode remains and the trap simply returns
+ * as normal with the appropriate error code in RET0.
+ */
+#define HV_FAST_MMU_ENABLE 0x27
+
+/* mmu_unmap_perm_addr()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MMU_UNMAP_PERM_ADDR
+ * ARG0: virtual address
+ * ARG1: reserved, must be zero
+ * ARG2: flags (HV_MMU_{IMMU,DMMU})
+ * RET0: status
+ * ERRORS: EINVAL Invalid virtual address or flags value
+ * ENOMAP Specified mapping was not found
+ *
+ * Demaps any permanent page mapping (established via
+ * mmu_map_perm_addr()) at the given virtual address for context 0 on
+ * the current virtual CPU. Any virtual tagged caches are guaranteed
+ * to be kept consistent.
+ */
+#define HV_FAST_MMU_UNMAP_PERM_ADDR 0x28
+
+/* mmu_tsb_ctx0_info()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MMU_TSB_CTX0_INFO
+ * ARG0: max TSBs
+ * ARG1: buffer pointer
+ * RET0: status
+ * RET1: number of TSBs
+ * ERRORS: EINVAL Supplied buffer is too small
+ * EBADALIGN The buffer pointer is badly aligned
+ * ENORADDR Invalid real address for buffer pointer
+ *
+ * Return the TSB configuration as previous defined by mmu_tsb_ctx0()
+ * into the provided buffer. The size of the buffer is given in ARG1
+ * in terms of the number of TSB description entries.
+ *
+ * Upon return, RET1 always contains the number of TSB descriptions
+ * previously configured. If zero TSBs were configured, EOK is
+ * returned with RET1 containing 0.
+ */
+#define HV_FAST_MMU_TSB_CTX0_INFO 0x29
+
+/* mmu_tsb_ctxnon0_info()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MMU_TSB_CTXNON0_INFO
+ * ARG0: max TSBs
+ * ARG1: buffer pointer
+ * RET0: status
+ * RET1: number of TSBs
+ * ERRORS: EINVAL Supplied buffer is too small
+ * EBADALIGN The buffer pointer is badly aligned
+ * ENORADDR Invalid real address for buffer pointer
+ *
+ * Return the TSB configuration as previous defined by
+ * mmu_tsb_ctxnon0() into the provided buffer. The size of the buffer
+ * is given in ARG1 in terms of the number of TSB description entries.
+ *
+ * Upon return, RET1 always contains the number of TSB descriptions
+ * previously configured. If zero TSBs were configured, EOK is
+ * returned with RET1 containing 0.
+ */
+#define HV_FAST_MMU_TSB_CTXNON0_INFO 0x2a
+
+/* mmu_fault_area_info()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MMU_FAULT_AREA_INFO
+ * RET0: status
+ * RET1: fault area real address
+ * ERRORS: No errors defined.
+ *
+ * Return the currently defined MMU fault status area for the current
+ * CPU. The real address of the fault status area is returned in
+ * RET1, or 0 is returned in RET1 if no fault status area is defined.
+ *
+ * Note: mmu_fault_area_conf() may be called with the return value (RET1)
+ * from this service if there is a need to save and restore the fault
+ * area for a cpu.
+ */
+#define HV_FAST_MMU_FAULT_AREA_INFO 0x2b
+
+/* Cache and Memory services. */
+
+/* mem_scrub()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MEM_SCRUB
+ * ARG0: real address
+ * ARG1: length
+ * RET0: status
+ * RET1: length scrubbed
+ * ERRORS: ENORADDR Invalid real address
+ * EBADALIGN Start address or length are not correctly
+ * aligned
+ * EINVAL Length is zero
+ *
+ * Zero the memory contents in the range real address to real address
+ * plus length minus 1. Also, valid ECC will be generated for that
+ * memory address range. Scrubbing is started at the given real
+ * address, but may not scrub the entire given length. The actual
+ * length scrubbed will be returned in RET1.
+ *
+ * The real address and length must be aligned on an 8K boundary, or
+ * contain the start address and length from a sun4v error report.
+ *
+ * Note: There are two uses for this function. The first use is to block clear
+ * and initialize memory and the second is to scrub an u ncorrectable
+ * error reported via a resumable or non-resumable trap. The second
+ * use requires the arguments to be equal to the real address and length
+ * provided in a sun4v memory error report.
+ */
+#define HV_FAST_MEM_SCRUB 0x31
+
+/* mem_sync()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MEM_SYNC
+ * ARG0: real address
+ * ARG1: length
+ * RET0: status
+ * RET1: length synced
+ * ERRORS: ENORADDR Invalid real address
+ * EBADALIGN Start address or length are not correctly
+ * aligned
+ * EINVAL Length is zero
+ *
+ * Force the next access within the real address to real address plus
+ * length minus 1 to be fetches from main system memory. Less than
+ * the given length may be synced, the actual amount synced is
+ * returned in RET1. The real address and length must be aligned on
+ * an 8K boundary.
+ */
+#define HV_FAST_MEM_SYNC 0x32
+
+/* Time of day services.
+ *
+ * The hypervisor maintains the time of day on a per-domain basis.
+ * Changing the time of day in one domain does not affect the time of
+ * day on any other domain.
+ *
+ * Time is described by a single unsigned 64-bit word which is the
+ * number of seconds since the UNIX Epoch (00:00:00 UTC, January 1,
+ * 1970).
+ */
+
+/* tod_get()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_TOD_GET
+ * RET0: status
+ * RET1: TOD
+ * ERRORS: EWOULDBLOCK TOD resource is temporarily unavailable
+ * ENOTSUPPORTED If TOD not supported on this platform
+ *
+ * Return the current time of day. May block if TOD access is
+ * temporarily not possible.
+ */
+#define HV_FAST_TOD_GET 0x50
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_tod_get(unsigned long *time);
+#endif
+
+/* tod_set()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_TOD_SET
+ * ARG0: TOD
+ * RET0: status
+ * ERRORS: EWOULDBLOCK TOD resource is temporarily unavailable
+ * ENOTSUPPORTED If TOD not supported on this platform
+ *
+ * The current time of day is set to the value specified in ARG0. May
+ * block if TOD access is temporarily not possible.
+ */
+#define HV_FAST_TOD_SET 0x51
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_tod_set(unsigned long time);
+#endif
+
+/* Console services */
+
+/* con_getchar()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_CONS_GETCHAR
+ * RET0: status
+ * RET1: character
+ * ERRORS: EWOULDBLOCK No character available.
+ *
+ * Returns a character from the console device. If no character is
+ * available then an EWOULDBLOCK error is returned. If a character is
+ * available, then the returned status is EOK and the character value
+ * is in RET1.
+ *
+ * A virtual BREAK is represented by the 64-bit value -1.
+ *
+ * A virtual HUP signal is represented by the 64-bit value -2.
+ */
+#define HV_FAST_CONS_GETCHAR 0x60
+
+/* con_putchar()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_CONS_PUTCHAR
+ * ARG0: character
+ * RET0: status
+ * ERRORS: EINVAL Illegal character
+ * EWOULDBLOCK Output buffer currently full, would block
+ *
+ * Send a character to the console device. Only character values
+ * between 0 and 255 may be used. Values outside this range are
+ * invalid except for the 64-bit value -1 which is used to send a
+ * virtual BREAK.
+ */
+#define HV_FAST_CONS_PUTCHAR 0x61
+
+/* con_read()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_CONS_READ
+ * ARG0: buffer real address
+ * ARG1: buffer size in bytes
+ * RET0: status
+ * RET1: bytes read or BREAK or HUP
+ * ERRORS: EWOULDBLOCK No character available.
+ *
+ * Reads characters into a buffer from the console device. If no
+ * character is available then an EWOULDBLOCK error is returned.
+ * If a character is available, then the returned status is EOK
+ * and the number of bytes read into the given buffer is provided
+ * in RET1.
+ *
+ * A virtual BREAK is represented by the 64-bit RET1 value -1.
+ *
+ * A virtual HUP signal is represented by the 64-bit RET1 value -2.
+ *
+ * If BREAK or HUP are indicated, no bytes were read into buffer.
+ */
+#define HV_FAST_CONS_READ 0x62
+
+/* con_write()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_CONS_WRITE
+ * ARG0: buffer real address
+ * ARG1: buffer size in bytes
+ * RET0: status
+ * RET1: bytes written
+ * ERRORS: EWOULDBLOCK Output buffer currently full, would block
+ *
+ * Send a characters in buffer to the console device. Breaks must be
+ * sent using con_putchar().
+ */
+#define HV_FAST_CONS_WRITE 0x63
+
+#ifndef __ASSEMBLY__
+long sun4v_con_getchar(long *status);
+long sun4v_con_putchar(long c);
+long sun4v_con_read(unsigned long buffer,
+ unsigned long size,
+ unsigned long *bytes_read);
+unsigned long sun4v_con_write(unsigned long buffer,
+ unsigned long size,
+ unsigned long *bytes_written);
+#endif
+
+/* mach_set_soft_state()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MACH_SET_SOFT_STATE
+ * ARG0: software state
+ * ARG1: software state description pointer
+ * RET0: status
+ * ERRORS: EINVAL software state not valid or software state
+ * description is not NULL terminated
+ * ENORADDR software state description pointer is not a
+ * valid real address
+ * EBADALIGNED software state description is not correctly
+ * aligned
+ *
+ * This allows the guest to report it's soft state to the hypervisor. There
+ * are two primary components to this state. The first part states whether
+ * the guest software is running or not. The second containts optional
+ * details specific to the software.
+ *
+ * The software state argument is defined below in HV_SOFT_STATE_*, and
+ * indicates whether the guest is operating normally or in a transitional
+ * state.
+ *
+ * The software state description argument is a real address of a data buffer
+ * of size 32-bytes aligned on a 32-byte boundary. It is treated as a NULL
+ * terminated 7-bit ASCII string of up to 31 characters not including the
+ * NULL termination.
+ */
+#define HV_FAST_MACH_SET_SOFT_STATE 0x70
+#define HV_SOFT_STATE_NORMAL 0x01
+#define HV_SOFT_STATE_TRANSITION 0x02
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_mach_set_soft_state(unsigned long soft_state,
+ unsigned long msg_string_ra);
+#endif
+
+/* mach_get_soft_state()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MACH_GET_SOFT_STATE
+ * ARG0: software state description pointer
+ * RET0: status
+ * RET1: software state
+ * ERRORS: ENORADDR software state description pointer is not a
+ * valid real address
+ * EBADALIGNED software state description is not correctly
+ * aligned
+ *
+ * Retrieve the current value of the guest's software state. The rules
+ * for the software state pointer are the same as for mach_set_soft_state()
+ * above.
+ */
+#define HV_FAST_MACH_GET_SOFT_STATE 0x71
+
+/* svc_send()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_SVC_SEND
+ * ARG0: service ID
+ * ARG1: buffer real address
+ * ARG2: buffer size
+ * RET0: STATUS
+ * RET1: sent_bytes
+ *
+ * Be careful, all output registers are clobbered by this operation,
+ * so for example it is not possible to save away a value in %o4
+ * across the trap.
+ */
+#define HV_FAST_SVC_SEND 0x80
+
+/* svc_recv()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_SVC_RECV
+ * ARG0: service ID
+ * ARG1: buffer real address
+ * ARG2: buffer size
+ * RET0: STATUS
+ * RET1: recv_bytes
+ *
+ * Be careful, all output registers are clobbered by this operation,
+ * so for example it is not possible to save away a value in %o4
+ * across the trap.
+ */
+#define HV_FAST_SVC_RECV 0x81
+
+/* svc_getstatus()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_SVC_GETSTATUS
+ * ARG0: service ID
+ * RET0: STATUS
+ * RET1: status bits
+ */
+#define HV_FAST_SVC_GETSTATUS 0x82
+
+/* svc_setstatus()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_SVC_SETSTATUS
+ * ARG0: service ID
+ * ARG1: bits to set
+ * RET0: STATUS
+ */
+#define HV_FAST_SVC_SETSTATUS 0x83
+
+/* svc_clrstatus()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_SVC_CLRSTATUS
+ * ARG0: service ID
+ * ARG1: bits to clear
+ * RET0: STATUS
+ */
+#define HV_FAST_SVC_CLRSTATUS 0x84
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_svc_send(unsigned long svc_id,
+ unsigned long buffer,
+ unsigned long buffer_size,
+ unsigned long *sent_bytes);
+unsigned long sun4v_svc_recv(unsigned long svc_id,
+ unsigned long buffer,
+ unsigned long buffer_size,
+ unsigned long *recv_bytes);
+unsigned long sun4v_svc_getstatus(unsigned long svc_id,
+ unsigned long *status_bits);
+unsigned long sun4v_svc_setstatus(unsigned long svc_id,
+ unsigned long status_bits);
+unsigned long sun4v_svc_clrstatus(unsigned long svc_id,
+ unsigned long status_bits);
+#endif
+
+/* Trap trace services.
+ *
+ * The hypervisor provides a trap tracing capability for privileged
+ * code running on each virtual CPU. Privileged code provides a
+ * round-robin trap trace queue within which the hypervisor writes
+ * 64-byte entries detailing hyperprivileged traps taken n behalf of
+ * privileged code. This is provided as a debugging capability for
+ * privileged code.
+ *
+ * The trap trace control structure is 64-bytes long and placed at the
+ * start (offset 0) of the trap trace buffer, and is described as
+ * follows:
+ */
+#ifndef __ASSEMBLY__
+struct hv_trap_trace_control {
+ unsigned long head_offset;
+ unsigned long tail_offset;
+ unsigned long __reserved[0x30 / sizeof(unsigned long)];
+};
+#endif
+#define HV_TRAP_TRACE_CTRL_HEAD_OFFSET 0x00
+#define HV_TRAP_TRACE_CTRL_TAIL_OFFSET 0x08
+
+/* The head offset is the offset of the most recently completed entry
+ * in the trap-trace buffer. The tail offset is the offset of the
+ * next entry to be written. The control structure is owned and
+ * modified by the hypervisor. A guest may not modify the control
+ * structure contents. Attempts to do so will result in undefined
+ * behavior for the guest.
+ *
+ * Each trap trace buffer entry is laid out as follows:
+ */
+#ifndef __ASSEMBLY__
+struct hv_trap_trace_entry {
+ unsigned char type; /* Hypervisor or guest entry? */
+ unsigned char hpstate; /* Hyper-privileged state */
+ unsigned char tl; /* Trap level */
+ unsigned char gl; /* Global register level */
+ unsigned short tt; /* Trap type */
+ unsigned short tag; /* Extended trap identifier */
+ unsigned long tstate; /* Trap state */
+ unsigned long tick; /* Tick */
+ unsigned long tpc; /* Trap PC */
+ unsigned long f1; /* Entry specific */
+ unsigned long f2; /* Entry specific */
+ unsigned long f3; /* Entry specific */
+ unsigned long f4; /* Entry specific */
+};
+#endif
+#define HV_TRAP_TRACE_ENTRY_TYPE 0x00
+#define HV_TRAP_TRACE_ENTRY_HPSTATE 0x01
+#define HV_TRAP_TRACE_ENTRY_TL 0x02
+#define HV_TRAP_TRACE_ENTRY_GL 0x03
+#define HV_TRAP_TRACE_ENTRY_TT 0x04
+#define HV_TRAP_TRACE_ENTRY_TAG 0x06
+#define HV_TRAP_TRACE_ENTRY_TSTATE 0x08
+#define HV_TRAP_TRACE_ENTRY_TICK 0x10
+#define HV_TRAP_TRACE_ENTRY_TPC 0x18
+#define HV_TRAP_TRACE_ENTRY_F1 0x20
+#define HV_TRAP_TRACE_ENTRY_F2 0x28
+#define HV_TRAP_TRACE_ENTRY_F3 0x30
+#define HV_TRAP_TRACE_ENTRY_F4 0x38
+
+/* The type field is encoded as follows. */
+#define HV_TRAP_TYPE_UNDEF 0x00 /* Entry content undefined */
+#define HV_TRAP_TYPE_HV 0x01 /* Hypervisor trap entry */
+#define HV_TRAP_TYPE_GUEST 0xff /* Added via ttrace_addentry() */
+
+/* ttrace_buf_conf()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_TTRACE_BUF_CONF
+ * ARG0: real address
+ * ARG1: number of entries
+ * RET0: status
+ * RET1: number of entries
+ * ERRORS: ENORADDR Invalid real address
+ * EINVAL Size is too small
+ * EBADALIGN Real address not aligned on 64-byte boundary
+ *
+ * Requests hypervisor trap tracing and declares a virtual CPU's trap
+ * trace buffer to the hypervisor. The real address supplies the real
+ * base address of the trap trace queue and must be 64-byte aligned.
+ * Specifying a value of 0 for the number of entries disables trap
+ * tracing for the calling virtual CPU. The buffer allocated must be
+ * sized for a power of two number of 64-byte trap trace entries plus
+ * an initial 64-byte control structure.
+ *
+ * This may be invoked any number of times so that a virtual CPU may
+ * relocate a trap trace buffer or create "snapshots" of information.
+ *
+ * If the real address is illegal or badly aligned, then trap tracing
+ * is disabled and an error is returned.
+ *
+ * Upon failure with EINVAL, this service call returns in RET1 the
+ * minimum number of buffer entries required. Upon other failures
+ * RET1 is undefined.
+ */
+#define HV_FAST_TTRACE_BUF_CONF 0x90
+
+/* ttrace_buf_info()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_TTRACE_BUF_INFO
+ * RET0: status
+ * RET1: real address
+ * RET2: size
+ * ERRORS: None defined.
+ *
+ * Returns the size and location of the previously declared trap-trace
+ * buffer. In the event that no buffer was previously defined, or the
+ * buffer is disabled, this call will return a size of zero bytes.
+ */
+#define HV_FAST_TTRACE_BUF_INFO 0x91
+
+/* ttrace_enable()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_TTRACE_ENABLE
+ * ARG0: enable
+ * RET0: status
+ * RET1: previous enable state
+ * ERRORS: EINVAL No trap trace buffer currently defined
+ *
+ * Enable or disable trap tracing, and return the previous enabled
+ * state in RET1. Future systems may define various flags for the
+ * enable argument (ARG0), for the moment a guest should pass
+ * "(uint64_t) -1" to enable, and "(uint64_t) 0" to disable all
+ * tracing - which will ensure future compatibility.
+ */
+#define HV_FAST_TTRACE_ENABLE 0x92
+
+/* ttrace_freeze()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_TTRACE_FREEZE
+ * ARG0: freeze
+ * RET0: status
+ * RET1: previous freeze state
+ * ERRORS: EINVAL No trap trace buffer currently defined
+ *
+ * Freeze or unfreeze trap tracing, returning the previous freeze
+ * state in RET1. A guest should pass a non-zero value to freeze and
+ * a zero value to unfreeze all tracing. The returned previous state
+ * is 0 for not frozen and 1 for frozen.
+ */
+#define HV_FAST_TTRACE_FREEZE 0x93
+
+/* ttrace_addentry()
+ * TRAP: HV_TTRACE_ADDENTRY_TRAP
+ * ARG0: tag (16-bits)
+ * ARG1: data word 0
+ * ARG2: data word 1
+ * ARG3: data word 2
+ * ARG4: data word 3
+ * RET0: status
+ * ERRORS: EINVAL No trap trace buffer currently defined
+ *
+ * Add an entry to the trap trace buffer. Upon return only ARG0/RET0
+ * is modified - none of the other registers holding arguments are
+ * volatile across this hypervisor service.
+ */
+
+/* Core dump services.
+ *
+ * Since the hypervisor viraulizes and thus obscures a lot of the
+ * physical machine layout and state, traditional OS crash dumps can
+ * be difficult to diagnose especially when the problem is a
+ * configuration error of some sort.
+ *
+ * The dump services provide an opaque buffer into which the
+ * hypervisor can place it's internal state in order to assist in
+ * debugging such situations. The contents are opaque and extremely
+ * platform and hypervisor implementation specific. The guest, during
+ * a core dump, requests that the hypervisor update any information in
+ * the dump buffer in preparation to being dumped as part of the
+ * domain's memory image.
+ */
+
+/* dump_buf_update()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_DUMP_BUF_UPDATE
+ * ARG0: real address
+ * ARG1: size
+ * RET0: status
+ * RET1: required size of dump buffer
+ * ERRORS: ENORADDR Invalid real address
+ * EBADALIGN Real address is not aligned on a 64-byte
+ * boundary
+ * EINVAL Size is non-zero but less than minimum size
+ * required
+ * ENOTSUPPORTED Operation not supported on current logical
+ * domain
+ *
+ * Declare a domain dump buffer to the hypervisor. The real address
+ * provided for the domain dump buffer must be 64-byte aligned. The
+ * size specifies the size of the dump buffer and may be larger than
+ * the minimum size specified in the machine description. The
+ * hypervisor will fill the dump buffer with opaque data.
+ *
+ * Note: A guest may elect to include dump buffer contents as part of a crash
+ * dump to assist with debugging. This function may be called any number
+ * of times so that a guest may relocate a dump buffer, or create
+ * "snapshots" of any dump-buffer information. Each call to
+ * dump_buf_update() atomically declares the new dump buffer to the
+ * hypervisor.
+ *
+ * A specified size of 0 unconfigures the dump buffer. If the real
+ * address is illegal or badly aligned, then any currently active dump
+ * buffer is disabled and an error is returned.
+ *
+ * In the event that the call fails with EINVAL, RET1 contains the
+ * minimum size requires by the hypervisor for a valid dump buffer.
+ */
+#define HV_FAST_DUMP_BUF_UPDATE 0x94
+
+/* dump_buf_info()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_DUMP_BUF_INFO
+ * RET0: status
+ * RET1: real address of current dump buffer
+ * RET2: size of current dump buffer
+ * ERRORS: No errors defined.
+ *
+ * Return the currently configures dump buffer description. A
+ * returned size of 0 bytes indicates an undefined dump buffer. In
+ * this case the return address in RET1 is undefined.
+ */
+#define HV_FAST_DUMP_BUF_INFO 0x95
+
+/* Device interrupt services.
+ *
+ * Device interrupts are allocated to system bus bridges by the hypervisor,
+ * and described to OBP in the machine description. OBP then describes
+ * these interrupts to the OS via properties in the device tree.
+ *
+ * Terminology:
+ *
+ * cpuid Unique opaque value which represents a target cpu.
+ *
+ * devhandle Device handle. It uniquely identifies a device, and
+ * consistes of the lower 28-bits of the hi-cell of the
+ * first entry of the device's "reg" property in the
+ * OBP device tree.
+ *
+ * devino Device interrupt number. Specifies the relative
+ * interrupt number within the device. The unique
+ * combination of devhandle and devino are used to
+ * identify a specific device interrupt.
+ *
+ * Note: The devino value is the same as the values in the
+ * "interrupts" property or "interrupt-map" property
+ * in the OBP device tree for that device.
+ *
+ * sysino System interrupt number. A 64-bit unsigned interger
+ * representing a unique interrupt within a virtual
+ * machine.
+ *
+ * intr_state A flag representing the interrupt state for a given
+ * sysino. The state values are defined below.
+ *
+ * intr_enabled A flag representing the 'enabled' state for a given
+ * sysino. The enable values are defined below.
+ */
+
+#define HV_INTR_STATE_IDLE 0 /* Nothing pending */
+#define HV_INTR_STATE_RECEIVED 1 /* Interrupt received by hardware */
+#define HV_INTR_STATE_DELIVERED 2 /* Interrupt delivered to queue */
+
+#define HV_INTR_DISABLED 0 /* sysino not enabled */
+#define HV_INTR_ENABLED 1 /* sysino enabled */
+
+/* intr_devino_to_sysino()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_INTR_DEVINO2SYSINO
+ * ARG0: devhandle
+ * ARG1: devino
+ * RET0: status
+ * RET1: sysino
+ * ERRORS: EINVAL Invalid devhandle/devino
+ *
+ * Converts a device specific interrupt number of the given
+ * devhandle/devino into a system specific ino (sysino).
+ */
+#define HV_FAST_INTR_DEVINO2SYSINO 0xa0
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_devino_to_sysino(unsigned long devhandle,
+ unsigned long devino);
+#endif
+
+/* intr_getenabled()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_INTR_GETENABLED
+ * ARG0: sysino
+ * RET0: status
+ * RET1: intr_enabled (HV_INTR_{DISABLED,ENABLED})
+ * ERRORS: EINVAL Invalid sysino
+ *
+ * Returns interrupt enabled state in RET1 for the interrupt defined
+ * by the given sysino.
+ */
+#define HV_FAST_INTR_GETENABLED 0xa1
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_intr_getenabled(unsigned long sysino);
+#endif
+
+/* intr_setenabled()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_INTR_SETENABLED
+ * ARG0: sysino
+ * ARG1: intr_enabled (HV_INTR_{DISABLED,ENABLED})
+ * RET0: status
+ * ERRORS: EINVAL Invalid sysino or intr_enabled value
+ *
+ * Set the 'enabled' state of the interrupt sysino.
+ */
+#define HV_FAST_INTR_SETENABLED 0xa2
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_intr_setenabled(unsigned long sysino,
+ unsigned long intr_enabled);
+#endif
+
+/* intr_getstate()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_INTR_GETSTATE
+ * ARG0: sysino
+ * RET0: status
+ * RET1: intr_state (HV_INTR_STATE_*)
+ * ERRORS: EINVAL Invalid sysino
+ *
+ * Returns current state of the interrupt defined by the given sysino.
+ */
+#define HV_FAST_INTR_GETSTATE 0xa3
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_intr_getstate(unsigned long sysino);
+#endif
+
+/* intr_setstate()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_INTR_SETSTATE
+ * ARG0: sysino
+ * ARG1: intr_state (HV_INTR_STATE_*)
+ * RET0: status
+ * ERRORS: EINVAL Invalid sysino or intr_state value
+ *
+ * Sets the current state of the interrupt described by the given sysino
+ * value.
+ *
+ * Note: Setting the state to HV_INTR_STATE_IDLE clears any pending
+ * interrupt for sysino.
+ */
+#define HV_FAST_INTR_SETSTATE 0xa4
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_intr_setstate(unsigned long sysino, unsigned long intr_state);
+#endif
+
+/* intr_gettarget()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_INTR_GETTARGET
+ * ARG0: sysino
+ * RET0: status
+ * RET1: cpuid
+ * ERRORS: EINVAL Invalid sysino
+ *
+ * Returns CPU that is the current target of the interrupt defined by
+ * the given sysino. The CPU value returned is undefined if the target
+ * has not been set via intr_settarget().
+ */
+#define HV_FAST_INTR_GETTARGET 0xa5
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_intr_gettarget(unsigned long sysino);
+#endif
+
+/* intr_settarget()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_INTR_SETTARGET
+ * ARG0: sysino
+ * ARG1: cpuid
+ * RET0: status
+ * ERRORS: EINVAL Invalid sysino
+ * ENOCPU Invalid cpuid
+ *
+ * Set the target CPU for the interrupt defined by the given sysino.
+ */
+#define HV_FAST_INTR_SETTARGET 0xa6
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_intr_settarget(unsigned long sysino, unsigned long cpuid);
+#endif
+
+/* vintr_get_cookie()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_VINTR_GET_COOKIE
+ * ARG0: device handle
+ * ARG1: device ino
+ * RET0: status
+ * RET1: cookie
+ */
+#define HV_FAST_VINTR_GET_COOKIE 0xa7
+
+/* vintr_set_cookie()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_VINTR_SET_COOKIE
+ * ARG0: device handle
+ * ARG1: device ino
+ * ARG2: cookie
+ * RET0: status
+ */
+#define HV_FAST_VINTR_SET_COOKIE 0xa8
+
+/* vintr_get_valid()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_VINTR_GET_VALID
+ * ARG0: device handle
+ * ARG1: device ino
+ * RET0: status
+ * RET1: valid state
+ */
+#define HV_FAST_VINTR_GET_VALID 0xa9
+
+/* vintr_set_valid()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_VINTR_SET_VALID
+ * ARG0: device handle
+ * ARG1: device ino
+ * ARG2: valid state
+ * RET0: status
+ */
+#define HV_FAST_VINTR_SET_VALID 0xaa
+
+/* vintr_get_state()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_VINTR_GET_STATE
+ * ARG0: device handle
+ * ARG1: device ino
+ * RET0: status
+ * RET1: state
+ */
+#define HV_FAST_VINTR_GET_STATE 0xab
+
+/* vintr_set_state()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_VINTR_SET_STATE
+ * ARG0: device handle
+ * ARG1: device ino
+ * ARG2: state
+ * RET0: status
+ */
+#define HV_FAST_VINTR_SET_STATE 0xac
+
+/* vintr_get_target()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_VINTR_GET_TARGET
+ * ARG0: device handle
+ * ARG1: device ino
+ * RET0: status
+ * RET1: cpuid
+ */
+#define HV_FAST_VINTR_GET_TARGET 0xad
+
+/* vintr_set_target()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_VINTR_SET_TARGET
+ * ARG0: device handle
+ * ARG1: device ino
+ * ARG2: cpuid
+ * RET0: status
+ */
+#define HV_FAST_VINTR_SET_TARGET 0xae
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_vintr_get_cookie(unsigned long dev_handle,
+ unsigned long dev_ino,
+ unsigned long *cookie);
+unsigned long sun4v_vintr_set_cookie(unsigned long dev_handle,
+ unsigned long dev_ino,
+ unsigned long cookie);
+unsigned long sun4v_vintr_get_valid(unsigned long dev_handle,
+ unsigned long dev_ino,
+ unsigned long *valid);
+unsigned long sun4v_vintr_set_valid(unsigned long dev_handle,
+ unsigned long dev_ino,
+ unsigned long valid);
+unsigned long sun4v_vintr_get_state(unsigned long dev_handle,
+ unsigned long dev_ino,
+ unsigned long *state);
+unsigned long sun4v_vintr_set_state(unsigned long dev_handle,
+ unsigned long dev_ino,
+ unsigned long state);
+unsigned long sun4v_vintr_get_target(unsigned long dev_handle,
+ unsigned long dev_ino,
+ unsigned long *cpuid);
+unsigned long sun4v_vintr_set_target(unsigned long dev_handle,
+ unsigned long dev_ino,
+ unsigned long cpuid);
+#endif
+
+/* PCI IO services.
+ *
+ * See the terminology descriptions in the device interrupt services
+ * section above as those apply here too. Here are terminology
+ * definitions specific to these PCI IO services:
+ *
+ * tsbnum TSB number. Indentifies which io-tsb is used.
+ * For this version of the specification, tsbnum
+ * must be zero.
+ *
+ * tsbindex TSB index. Identifies which entry in the TSB
+ * is used. The first entry is zero.
+ *
+ * tsbid A 64-bit aligned data structure which contains
+ * a tsbnum and a tsbindex. Bits 63:32 contain the
+ * tsbnum and bits 31:00 contain the tsbindex.
+ *
+ * Use the HV_PCI_TSBID() macro to construct such
+ * values.
+ *
+ * io_attributes IO attributes for IOMMU mappings. One of more
+ * of the attritbute bits are stores in a 64-bit
+ * value. The values are defined below.
+ *
+ * r_addr 64-bit real address
+ *
+ * pci_device PCI device address. A PCI device address identifies
+ * a specific device on a specific PCI bus segment.
+ * A PCI device address ia a 32-bit unsigned integer
+ * with the following format:
+ *
+ * 00000000.bbbbbbbb.dddddfff.00000000
+ *
+ * Use the HV_PCI_DEVICE_BUILD() macro to construct
+ * such values.
+ *
+ * pci_config_offset
+ * PCI configureation space offset. For conventional
+ * PCI a value between 0 and 255. For extended
+ * configuration space, a value between 0 and 4095.
+ *
+ * Note: For PCI configuration space accesses, the offset
+ * must be aligned to the access size.
+ *
+ * error_flag A return value which specifies if the action succeeded
+ * or failed. 0 means no error, non-0 means some error
+ * occurred while performing the service.
+ *
+ * io_sync_direction
+ * Direction definition for pci_dma_sync(), defined
+ * below in HV_PCI_SYNC_*.
+ *
+ * io_page_list A list of io_page_addresses, an io_page_address is
+ * a real address.
+ *
+ * io_page_list_p A pointer to an io_page_list.
+ *
+ * "size based byte swap" - Some functions do size based byte swapping
+ * which allows sw to access pointers and
+ * counters in native form when the processor
+ * operates in a different endianness than the
+ * IO bus. Size-based byte swapping converts a
+ * multi-byte field between big-endian and
+ * little-endian format.
+ */
+
+#define HV_PCI_MAP_ATTR_READ 0x01
+#define HV_PCI_MAP_ATTR_WRITE 0x02
+
+#define HV_PCI_DEVICE_BUILD(b,d,f) \
+ ((((b) & 0xff) << 16) | \
+ (((d) & 0x1f) << 11) | \
+ (((f) & 0x07) << 8))
+
+#define HV_PCI_TSBID(__tsb_num, __tsb_index) \
+ ((((u64)(__tsb_num)) << 32UL) | ((u64)(__tsb_index)))
+
+#define HV_PCI_SYNC_FOR_DEVICE 0x01
+#define HV_PCI_SYNC_FOR_CPU 0x02
+
+/* pci_iommu_map()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_IOMMU_MAP
+ * ARG0: devhandle
+ * ARG1: tsbid
+ * ARG2: #ttes
+ * ARG3: io_attributes
+ * ARG4: io_page_list_p
+ * RET0: status
+ * RET1: #ttes mapped
+ * ERRORS: EINVAL Invalid devhandle/tsbnum/tsbindex/io_attributes
+ * EBADALIGN Improperly aligned real address
+ * ENORADDR Invalid real address
+ *
+ * Create IOMMU mappings in the sun4v device defined by the given
+ * devhandle. The mappings are created in the TSB defined by the
+ * tsbnum component of the given tsbid. The first mapping is created
+ * in the TSB i ndex defined by the tsbindex component of the given tsbid.
+ * The call creates up to #ttes mappings, the first one at tsbnum, tsbindex,
+ * the second at tsbnum, tsbindex + 1, etc.
+ *
+ * All mappings are created with the attributes defined by the io_attributes
+ * argument. The page mapping addresses are described in the io_page_list
+ * defined by the given io_page_list_p, which is a pointer to the io_page_list.
+ * The first entry in the io_page_list is the address for the first iotte, the
+ * 2nd for the 2nd iotte, and so on.
+ *
+ * Each io_page_address in the io_page_list must be appropriately aligned.
+ * #ttes must be greater than zero. For this version of the spec, the tsbnum
+ * component of the given tsbid must be zero.
+ *
+ * Returns the actual number of mappings creates, which may be less than
+ * or equal to the argument #ttes. If the function returns a value which
+ * is less than the #ttes, the caller may continus to call the function with
+ * an updated tsbid, #ttes, io_page_list_p arguments until all pages are
+ * mapped.
+ *
+ * Note: This function does not imply an iotte cache flush. The guest must
+ * demap an entry before re-mapping it.
+ */
+#define HV_FAST_PCI_IOMMU_MAP 0xb0
+
+/* pci_iommu_demap()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_IOMMU_DEMAP
+ * ARG0: devhandle
+ * ARG1: tsbid
+ * ARG2: #ttes
+ * RET0: status
+ * RET1: #ttes demapped
+ * ERRORS: EINVAL Invalid devhandle/tsbnum/tsbindex
+ *
+ * Demap and flush IOMMU mappings in the device defined by the given
+ * devhandle. Demaps up to #ttes entries in the TSB defined by the tsbnum
+ * component of the given tsbid, starting at the TSB index defined by the
+ * tsbindex component of the given tsbid.
+ *
+ * For this version of the spec, the tsbnum of the given tsbid must be zero.
+ * #ttes must be greater than zero.
+ *
+ * Returns the actual number of ttes demapped, which may be less than or equal
+ * to the argument #ttes. If #ttes demapped is less than #ttes, the caller
+ * may continue to call this function with updated tsbid and #ttes arguments
+ * until all pages are demapped.
+ *
+ * Note: Entries do not have to be mapped to be demapped. A demap of an
+ * unmapped page will flush the entry from the tte cache.
+ */
+#define HV_FAST_PCI_IOMMU_DEMAP 0xb1
+
+/* pci_iommu_getmap()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_IOMMU_GETMAP
+ * ARG0: devhandle
+ * ARG1: tsbid
+ * RET0: status
+ * RET1: io_attributes
+ * RET2: real address
+ * ERRORS: EINVAL Invalid devhandle/tsbnum/tsbindex
+ * ENOMAP Mapping is not valid, no translation exists
+ *
+ * Read and return the mapping in the device described by the given devhandle
+ * and tsbid. If successful, the io_attributes shall be returned in RET1
+ * and the page address of the mapping shall be returned in RET2.
+ *
+ * For this version of the spec, the tsbnum component of the given tsbid
+ * must be zero.
+ */
+#define HV_FAST_PCI_IOMMU_GETMAP 0xb2
+
+/* pci_iommu_getbypass()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_IOMMU_GETBYPASS
+ * ARG0: devhandle
+ * ARG1: real address
+ * ARG2: io_attributes
+ * RET0: status
+ * RET1: io_addr
+ * ERRORS: EINVAL Invalid devhandle/io_attributes
+ * ENORADDR Invalid real address
+ * ENOTSUPPORTED Function not supported in this implementation.
+ *
+ * Create a "special" mapping in the device described by the given devhandle,
+ * for the given real address and attributes. Return the IO address in RET1
+ * if successful.
+ */
+#define HV_FAST_PCI_IOMMU_GETBYPASS 0xb3
+
+/* pci_config_get()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_CONFIG_GET
+ * ARG0: devhandle
+ * ARG1: pci_device
+ * ARG2: pci_config_offset
+ * ARG3: size
+ * RET0: status
+ * RET1: error_flag
+ * RET2: data
+ * ERRORS: EINVAL Invalid devhandle/pci_device/offset/size
+ * EBADALIGN pci_config_offset not size aligned
+ * ENOACCESS Access to this offset is not permitted
+ *
+ * Read PCI configuration space for the adapter described by the given
+ * devhandle. Read size (1, 2, or 4) bytes of data from the given
+ * pci_device, at pci_config_offset from the beginning of the device's
+ * configuration space. If there was no error, RET1 is set to zero and
+ * RET2 is set to the data read. Insignificant bits in RET2 are not
+ * guaranteed to have any specific value and therefore must be ignored.
+ *
+ * The data returned in RET2 is size based byte swapped.
+ *
+ * If an error occurs during the read, set RET1 to a non-zero value. The
+ * given pci_config_offset must be 'size' aligned.
+ */
+#define HV_FAST_PCI_CONFIG_GET 0xb4
+
+/* pci_config_put()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_CONFIG_PUT
+ * ARG0: devhandle
+ * ARG1: pci_device
+ * ARG2: pci_config_offset
+ * ARG3: size
+ * ARG4: data
+ * RET0: status
+ * RET1: error_flag
+ * ERRORS: EINVAL Invalid devhandle/pci_device/offset/size
+ * EBADALIGN pci_config_offset not size aligned
+ * ENOACCESS Access to this offset is not permitted
+ *
+ * Write PCI configuration space for the adapter described by the given
+ * devhandle. Write size (1, 2, or 4) bytes of data in a single operation,
+ * at pci_config_offset from the beginning of the device's configuration
+ * space. The data argument contains the data to be written to configuration
+ * space. Prior to writing, the data is size based byte swapped.
+ *
+ * If an error occurs during the write access, do not generate an error
+ * report, do set RET1 to a non-zero value. Otherwise RET1 is zero.
+ * The given pci_config_offset must be 'size' aligned.
+ *
+ * This function is permitted to read from offset zero in the configuration
+ * space described by the given pci_device if necessary to ensure that the
+ * write access to config space completes.
+ */
+#define HV_FAST_PCI_CONFIG_PUT 0xb5
+
+/* pci_peek()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_PEEK
+ * ARG0: devhandle
+ * ARG1: real address
+ * ARG2: size
+ * RET0: status
+ * RET1: error_flag
+ * RET2: data
+ * ERRORS: EINVAL Invalid devhandle or size
+ * EBADALIGN Improperly aligned real address
+ * ENORADDR Bad real address
+ * ENOACCESS Guest access prohibited
+ *
+ * Attempt to read the IO address given by the given devhandle, real address,
+ * and size. Size must be 1, 2, 4, or 8. The read is performed as a single
+ * access operation using the given size. If an error occurs when reading
+ * from the given location, do not generate an error report, but return a
+ * non-zero value in RET1. If the read was successful, return zero in RET1
+ * and return the actual data read in RET2. The data returned is size based
+ * byte swapped.
+ *
+ * Non-significant bits in RET2 are not guaranteed to have any specific value
+ * and therefore must be ignored. If RET1 is returned as non-zero, the data
+ * value is not guaranteed to have any specific value and should be ignored.
+ *
+ * The caller must have permission to read from the given devhandle, real
+ * address, which must be an IO address. The argument real address must be a
+ * size aligned address.
+ *
+ * The hypervisor implementation of this function must block access to any
+ * IO address that the guest does not have explicit permission to access.
+ */
+#define HV_FAST_PCI_PEEK 0xb6
+
+/* pci_poke()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_POKE
+ * ARG0: devhandle
+ * ARG1: real address
+ * ARG2: size
+ * ARG3: data
+ * ARG4: pci_device
+ * RET0: status
+ * RET1: error_flag
+ * ERRORS: EINVAL Invalid devhandle, size, or pci_device
+ * EBADALIGN Improperly aligned real address
+ * ENORADDR Bad real address
+ * ENOACCESS Guest access prohibited
+ * ENOTSUPPORTED Function is not supported by implementation
+ *
+ * Attempt to write data to the IO address given by the given devhandle,
+ * real address, and size. Size must be 1, 2, 4, or 8. The write is
+ * performed as a single access operation using the given size. Prior to
+ * writing the data is size based swapped.
+ *
+ * If an error occurs when writing to the given location, do not generate an
+ * error report, but return a non-zero value in RET1. If the write was
+ * successful, return zero in RET1.
+ *
+ * pci_device describes the configuration address of the device being
+ * written to. The implementation may safely read from offset 0 with
+ * the configuration space of the device described by devhandle and
+ * pci_device in order to guarantee that the write portion of the operation
+ * completes
+ *
+ * Any error that occurs due to the read shall be reported using the normal
+ * error reporting mechanisms .. the read error is not suppressed.
+ *
+ * The caller must have permission to write to the given devhandle, real
+ * address, which must be an IO address. The argument real address must be a
+ * size aligned address. The caller must have permission to read from
+ * the given devhandle, pci_device cofiguration space offset 0.
+ *
+ * The hypervisor implementation of this function must block access to any
+ * IO address that the guest does not have explicit permission to access.
+ */
+#define HV_FAST_PCI_POKE 0xb7
+
+/* pci_dma_sync()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_DMA_SYNC
+ * ARG0: devhandle
+ * ARG1: real address
+ * ARG2: size
+ * ARG3: io_sync_direction
+ * RET0: status
+ * RET1: #synced
+ * ERRORS: EINVAL Invalid devhandle or io_sync_direction
+ * ENORADDR Bad real address
+ *
+ * Synchronize a memory region described by the given real address and size,
+ * for the device defined by the given devhandle using the direction(s)
+ * defined by the given io_sync_direction. The argument size is the size of
+ * the memory region in bytes.
+ *
+ * Return the actual number of bytes synchronized in the return value #synced,
+ * which may be less than or equal to the argument size. If the return
+ * value #synced is less than size, the caller must continue to call this
+ * function with updated real address and size arguments until the entire
+ * memory region is synchronized.
+ */
+#define HV_FAST_PCI_DMA_SYNC 0xb8
+
+/* PCI MSI services. */
+
+#define HV_MSITYPE_MSI32 0x00
+#define HV_MSITYPE_MSI64 0x01
+
+#define HV_MSIQSTATE_IDLE 0x00
+#define HV_MSIQSTATE_ERROR 0x01
+
+#define HV_MSIQ_INVALID 0x00
+#define HV_MSIQ_VALID 0x01
+
+#define HV_MSISTATE_IDLE 0x00
+#define HV_MSISTATE_DELIVERED 0x01
+
+#define HV_MSIVALID_INVALID 0x00
+#define HV_MSIVALID_VALID 0x01
+
+#define HV_PCIE_MSGTYPE_PME_MSG 0x18
+#define HV_PCIE_MSGTYPE_PME_ACK_MSG 0x1b
+#define HV_PCIE_MSGTYPE_CORR_MSG 0x30
+#define HV_PCIE_MSGTYPE_NONFATAL_MSG 0x31
+#define HV_PCIE_MSGTYPE_FATAL_MSG 0x33
+
+#define HV_MSG_INVALID 0x00
+#define HV_MSG_VALID 0x01
+
+/* pci_msiq_conf()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSIQ_CONF
+ * ARG0: devhandle
+ * ARG1: msiqid
+ * ARG2: real address
+ * ARG3: number of entries
+ * RET0: status
+ * ERRORS: EINVAL Invalid devhandle, msiqid or nentries
+ * EBADALIGN Improperly aligned real address
+ * ENORADDR Bad real address
+ *
+ * Configure the MSI queue given by the devhandle and msiqid arguments,
+ * and to be placed at the given real address and be of the given
+ * number of entries. The real address must be aligned exactly to match
+ * the queue size. Each queue entry is 64-bytes long, so f.e. a 32 entry
+ * queue must be aligned on a 2048 byte real address boundary. The MSI-EQ
+ * Head and Tail are initialized so that the MSI-EQ is 'empty'.
+ *
+ * Implementation Note: Certain implementations have fixed sized queues. In
+ * that case, number of entries must contain the correct
+ * value.
+ */
+#define HV_FAST_PCI_MSIQ_CONF 0xc0
+
+/* pci_msiq_info()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSIQ_INFO
+ * ARG0: devhandle
+ * ARG1: msiqid
+ * RET0: status
+ * RET1: real address
+ * RET2: number of entries
+ * ERRORS: EINVAL Invalid devhandle or msiqid
+ *
+ * Return the configuration information for the MSI queue described
+ * by the given devhandle and msiqid. The base address of the queue
+ * is returned in ARG1 and the number of entries is returned in ARG2.
+ * If the queue is unconfigured, the real address is undefined and the
+ * number of entries will be returned as zero.
+ */
+#define HV_FAST_PCI_MSIQ_INFO 0xc1
+
+/* pci_msiq_getvalid()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSIQ_GETVALID
+ * ARG0: devhandle
+ * ARG1: msiqid
+ * RET0: status
+ * RET1: msiqvalid (HV_MSIQ_VALID or HV_MSIQ_INVALID)
+ * ERRORS: EINVAL Invalid devhandle or msiqid
+ *
+ * Get the valid state of the MSI-EQ described by the given devhandle and
+ * msiqid.
+ */
+#define HV_FAST_PCI_MSIQ_GETVALID 0xc2
+
+/* pci_msiq_setvalid()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSIQ_SETVALID
+ * ARG0: devhandle
+ * ARG1: msiqid
+ * ARG2: msiqvalid (HV_MSIQ_VALID or HV_MSIQ_INVALID)
+ * RET0: status
+ * ERRORS: EINVAL Invalid devhandle or msiqid or msiqvalid
+ * value or MSI EQ is uninitialized
+ *
+ * Set the valid state of the MSI-EQ described by the given devhandle and
+ * msiqid to the given msiqvalid.
+ */
+#define HV_FAST_PCI_MSIQ_SETVALID 0xc3
+
+/* pci_msiq_getstate()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSIQ_GETSTATE
+ * ARG0: devhandle
+ * ARG1: msiqid
+ * RET0: status
+ * RET1: msiqstate (HV_MSIQSTATE_IDLE or HV_MSIQSTATE_ERROR)
+ * ERRORS: EINVAL Invalid devhandle or msiqid
+ *
+ * Get the state of the MSI-EQ described by the given devhandle and
+ * msiqid.
+ */
+#define HV_FAST_PCI_MSIQ_GETSTATE 0xc4
+
+/* pci_msiq_getvalid()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSIQ_GETVALID
+ * ARG0: devhandle
+ * ARG1: msiqid
+ * ARG2: msiqstate (HV_MSIQSTATE_IDLE or HV_MSIQSTATE_ERROR)
+ * RET0: status
+ * ERRORS: EINVAL Invalid devhandle or msiqid or msiqstate
+ * value or MSI EQ is uninitialized
+ *
+ * Set the state of the MSI-EQ described by the given devhandle and
+ * msiqid to the given msiqvalid.
+ */
+#define HV_FAST_PCI_MSIQ_SETSTATE 0xc5
+
+/* pci_msiq_gethead()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSIQ_GETHEAD
+ * ARG0: devhandle
+ * ARG1: msiqid
+ * RET0: status
+ * RET1: msiqhead
+ * ERRORS: EINVAL Invalid devhandle or msiqid
+ *
+ * Get the current MSI EQ queue head for the MSI-EQ described by the
+ * given devhandle and msiqid.
+ */
+#define HV_FAST_PCI_MSIQ_GETHEAD 0xc6
+
+/* pci_msiq_sethead()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSIQ_SETHEAD
+ * ARG0: devhandle
+ * ARG1: msiqid
+ * ARG2: msiqhead
+ * RET0: status
+ * ERRORS: EINVAL Invalid devhandle or msiqid or msiqhead,
+ * or MSI EQ is uninitialized
+ *
+ * Set the current MSI EQ queue head for the MSI-EQ described by the
+ * given devhandle and msiqid.
+ */
+#define HV_FAST_PCI_MSIQ_SETHEAD 0xc7
+
+/* pci_msiq_gettail()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSIQ_GETTAIL
+ * ARG0: devhandle
+ * ARG1: msiqid
+ * RET0: status
+ * RET1: msiqtail
+ * ERRORS: EINVAL Invalid devhandle or msiqid
+ *
+ * Get the current MSI EQ queue tail for the MSI-EQ described by the
+ * given devhandle and msiqid.
+ */
+#define HV_FAST_PCI_MSIQ_GETTAIL 0xc8
+
+/* pci_msi_getvalid()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSI_GETVALID
+ * ARG0: devhandle
+ * ARG1: msinum
+ * RET0: status
+ * RET1: msivalidstate
+ * ERRORS: EINVAL Invalid devhandle or msinum
+ *
+ * Get the current valid/enabled state for the MSI defined by the
+ * given devhandle and msinum.
+ */
+#define HV_FAST_PCI_MSI_GETVALID 0xc9
+
+/* pci_msi_setvalid()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSI_SETVALID
+ * ARG0: devhandle
+ * ARG1: msinum
+ * ARG2: msivalidstate
+ * RET0: status
+ * ERRORS: EINVAL Invalid devhandle or msinum or msivalidstate
+ *
+ * Set the current valid/enabled state for the MSI defined by the
+ * given devhandle and msinum.
+ */
+#define HV_FAST_PCI_MSI_SETVALID 0xca
+
+/* pci_msi_getmsiq()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSI_GETMSIQ
+ * ARG0: devhandle
+ * ARG1: msinum
+ * RET0: status
+ * RET1: msiqid
+ * ERRORS: EINVAL Invalid devhandle or msinum or MSI is unbound
+ *
+ * Get the MSI EQ that the MSI defined by the given devhandle and
+ * msinum is bound to.
+ */
+#define HV_FAST_PCI_MSI_GETMSIQ 0xcb
+
+/* pci_msi_setmsiq()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSI_SETMSIQ
+ * ARG0: devhandle
+ * ARG1: msinum
+ * ARG2: msitype
+ * ARG3: msiqid
+ * RET0: status
+ * ERRORS: EINVAL Invalid devhandle or msinum or msiqid
+ *
+ * Set the MSI EQ that the MSI defined by the given devhandle and
+ * msinum is bound to.
+ */
+#define HV_FAST_PCI_MSI_SETMSIQ 0xcc
+
+/* pci_msi_getstate()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSI_GETSTATE
+ * ARG0: devhandle
+ * ARG1: msinum
+ * RET0: status
+ * RET1: msistate
+ * ERRORS: EINVAL Invalid devhandle or msinum
+ *
+ * Get the state of the MSI defined by the given devhandle and msinum.
+ * If not initialized, return HV_MSISTATE_IDLE.
+ */
+#define HV_FAST_PCI_MSI_GETSTATE 0xcd
+
+/* pci_msi_setstate()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSI_SETSTATE
+ * ARG0: devhandle
+ * ARG1: msinum
+ * ARG2: msistate
+ * RET0: status
+ * ERRORS: EINVAL Invalid devhandle or msinum or msistate
+ *
+ * Set the state of the MSI defined by the given devhandle and msinum.
+ */
+#define HV_FAST_PCI_MSI_SETSTATE 0xce
+
+/* pci_msg_getmsiq()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSG_GETMSIQ
+ * ARG0: devhandle
+ * ARG1: msgtype
+ * RET0: status
+ * RET1: msiqid
+ * ERRORS: EINVAL Invalid devhandle or msgtype
+ *
+ * Get the MSI EQ of the MSG defined by the given devhandle and msgtype.
+ */
+#define HV_FAST_PCI_MSG_GETMSIQ 0xd0
+
+/* pci_msg_setmsiq()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSG_SETMSIQ
+ * ARG0: devhandle
+ * ARG1: msgtype
+ * ARG2: msiqid
+ * RET0: status
+ * ERRORS: EINVAL Invalid devhandle, msgtype, or msiqid
+ *
+ * Set the MSI EQ of the MSG defined by the given devhandle and msgtype.
+ */
+#define HV_FAST_PCI_MSG_SETMSIQ 0xd1
+
+/* pci_msg_getvalid()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSG_GETVALID
+ * ARG0: devhandle
+ * ARG1: msgtype
+ * RET0: status
+ * RET1: msgvalidstate
+ * ERRORS: EINVAL Invalid devhandle or msgtype
+ *
+ * Get the valid/enabled state of the MSG defined by the given
+ * devhandle and msgtype.
+ */
+#define HV_FAST_PCI_MSG_GETVALID 0xd2
+
+/* pci_msg_setvalid()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSG_SETVALID
+ * ARG0: devhandle
+ * ARG1: msgtype
+ * ARG2: msgvalidstate
+ * RET0: status
+ * ERRORS: EINVAL Invalid devhandle or msgtype or msgvalidstate
+ *
+ * Set the valid/enabled state of the MSG defined by the given
+ * devhandle and msgtype.
+ */
+#define HV_FAST_PCI_MSG_SETVALID 0xd3
+
+/* Logical Domain Channel services. */
+
+#define LDC_CHANNEL_DOWN 0
+#define LDC_CHANNEL_UP 1
+#define LDC_CHANNEL_RESETTING 2
+
+/* ldc_tx_qconf()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_LDC_TX_QCONF
+ * ARG0: channel ID
+ * ARG1: real address base of queue
+ * ARG2: num entries in queue
+ * RET0: status
+ *
+ * Configure transmit queue for the LDC endpoint specified by the
+ * given channel ID, to be placed at the given real address, and
+ * be of the given num entries. Num entries must be a power of two.
+ * The real address base of the queue must be aligned on the queue
+ * size. Each queue entry is 64-bytes, so for example, a 32 entry
+ * queue must be aligned on a 2048 byte real address boundary.
+ *
+ * Upon configuration of a valid transmit queue the head and tail
+ * pointers are set to a hypervisor specific identical value indicating
+ * that the queue initially is empty.
+ *
+ * The endpoint's transmit queue is un-configured if num entries is zero.
+ *
+ * The maximum number of entries for each queue for a specific cpu may be
+ * determined from the machine description. A transmit queue may be
+ * specified even in the event that the LDC is down (peer endpoint has no
+ * receive queue specified). Transmission will begin as soon as the peer
+ * endpoint defines a receive queue.
+ *
+ * It is recommended that a guest wait for a transmit queue to empty prior
+ * to reconfiguring it, or un-configuring it. Re or un-configuring of a
+ * non-empty transmit queue behaves exactly as defined above, however it
+ * is undefined as to how many of the pending entries in the original queue
+ * will be delivered prior to the re-configuration taking effect.
+ * Furthermore, as the queue configuration causes a reset of the head and
+ * tail pointers there is no way for a guest to determine how many entries
+ * have been sent after the configuration operation.
+ */
+#define HV_FAST_LDC_TX_QCONF 0xe0
+
+/* ldc_tx_qinfo()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_LDC_TX_QINFO
+ * ARG0: channel ID
+ * RET0: status
+ * RET1: real address base of queue
+ * RET2: num entries in queue
+ *
+ * Return the configuration info for the transmit queue of LDC endpoint
+ * defined by the given channel ID. The real address is the currently
+ * defined real address base of the defined queue, and num entries is the
+ * size of the queue in terms of number of entries.
+ *
+ * If the specified channel ID is a valid endpoint number, but no transmit
+ * queue has been defined this service will return success, but with num
+ * entries set to zero and the real address will have an undefined value.
+ */
+#define HV_FAST_LDC_TX_QINFO 0xe1
+
+/* ldc_tx_get_state()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_LDC_TX_GET_STATE
+ * ARG0: channel ID
+ * RET0: status
+ * RET1: head offset
+ * RET2: tail offset
+ * RET3: channel state
+ *
+ * Return the transmit state, and the head and tail queue pointers, for
+ * the transmit queue of the LDC endpoint defined by the given channel ID.
+ * The head and tail values are the byte offset of the head and tail
+ * positions of the transmit queue for the specified endpoint.
+ */
+#define HV_FAST_LDC_TX_GET_STATE 0xe2
+
+/* ldc_tx_set_qtail()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_LDC_TX_SET_QTAIL
+ * ARG0: channel ID
+ * ARG1: tail offset
+ * RET0: status
+ *
+ * Update the tail pointer for the transmit queue associated with the LDC
+ * endpoint defined by the given channel ID. The tail offset specified
+ * must be aligned on a 64 byte boundary, and calculated so as to increase
+ * the number of pending entries on the transmit queue. Any attempt to
+ * decrease the number of pending transmit queue entires is considered
+ * an invalid tail offset and will result in an EINVAL error.
+ *
+ * Since the tail of the transmit queue may not be moved backwards, the
+ * transmit queue may be flushed by configuring a new transmit queue,
+ * whereupon the hypervisor will configure the initial transmit head and
+ * tail pointers to be equal.
+ */
+#define HV_FAST_LDC_TX_SET_QTAIL 0xe3
+
+/* ldc_rx_qconf()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_LDC_RX_QCONF
+ * ARG0: channel ID
+ * ARG1: real address base of queue
+ * ARG2: num entries in queue
+ * RET0: status
+ *
+ * Configure receive queue for the LDC endpoint specified by the
+ * given channel ID, to be placed at the given real address, and
+ * be of the given num entries. Num entries must be a power of two.
+ * The real address base of the queue must be aligned on the queue
+ * size. Each queue entry is 64-bytes, so for example, a 32 entry
+ * queue must be aligned on a 2048 byte real address boundary.
+ *
+ * The endpoint's transmit queue is un-configured if num entries is zero.
+ *
+ * If a valid receive queue is specified for a local endpoint the LDC is
+ * in the up state for the purpose of transmission to this endpoint.
+ *
+ * The maximum number of entries for each queue for a specific cpu may be
+ * determined from the machine description.
+ *
+ * As receive queue configuration causes a reset of the queue's head and
+ * tail pointers there is no way for a gues to determine how many entries
+ * have been received between a preceding ldc_get_rx_state() API call
+ * and the completion of the configuration operation. It should be noted
+ * that datagram delivery is not guaranteed via domain channels anyway,
+ * and therefore any higher protocol should be resilient to datagram
+ * loss if necessary. However, to overcome this specific race potential
+ * it is recommended, for example, that a higher level protocol be employed
+ * to ensure either retransmission, or ensure that no datagrams are pending
+ * on the peer endpoint's transmit queue prior to the configuration process.
+ */
+#define HV_FAST_LDC_RX_QCONF 0xe4
+
+/* ldc_rx_qinfo()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_LDC_RX_QINFO
+ * ARG0: channel ID
+ * RET0: status
+ * RET1: real address base of queue
+ * RET2: num entries in queue
+ *
+ * Return the configuration info for the receive queue of LDC endpoint
+ * defined by the given channel ID. The real address is the currently
+ * defined real address base of the defined queue, and num entries is the
+ * size of the queue in terms of number of entries.
+ *
+ * If the specified channel ID is a valid endpoint number, but no receive
+ * queue has been defined this service will return success, but with num
+ * entries set to zero and the real address will have an undefined value.
+ */
+#define HV_FAST_LDC_RX_QINFO 0xe5
+
+/* ldc_rx_get_state()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_LDC_RX_GET_STATE
+ * ARG0: channel ID
+ * RET0: status
+ * RET1: head offset
+ * RET2: tail offset
+ * RET3: channel state
+ *
+ * Return the receive state, and the head and tail queue pointers, for
+ * the receive queue of the LDC endpoint defined by the given channel ID.
+ * The head and tail values are the byte offset of the head and tail
+ * positions of the receive queue for the specified endpoint.
+ */
+#define HV_FAST_LDC_RX_GET_STATE 0xe6
+
+/* ldc_rx_set_qhead()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_LDC_RX_SET_QHEAD
+ * ARG0: channel ID
+ * ARG1: head offset
+ * RET0: status
+ *
+ * Update the head pointer for the receive queue associated with the LDC
+ * endpoint defined by the given channel ID. The head offset specified
+ * must be aligned on a 64 byte boundary, and calculated so as to decrease
+ * the number of pending entries on the receive queue. Any attempt to
+ * increase the number of pending receive queue entires is considered
+ * an invalid head offset and will result in an EINVAL error.
+ *
+ * The receive queue may be flushed by setting the head offset equal
+ * to the current tail offset.
+ */
+#define HV_FAST_LDC_RX_SET_QHEAD 0xe7
+
+/* LDC Map Table Entry. Each slot is defined by a translation table
+ * entry, as specified by the LDC_MTE_* bits below, and a 64-bit
+ * hypervisor invalidation cookie.
+ */
+#define LDC_MTE_PADDR 0x0fffffffffffe000 /* pa[55:13] */
+#define LDC_MTE_COPY_W 0x0000000000000400 /* copy write access */
+#define LDC_MTE_COPY_R 0x0000000000000200 /* copy read access */
+#define LDC_MTE_IOMMU_W 0x0000000000000100 /* IOMMU write access */
+#define LDC_MTE_IOMMU_R 0x0000000000000080 /* IOMMU read access */
+#define LDC_MTE_EXEC 0x0000000000000040 /* execute */
+#define LDC_MTE_WRITE 0x0000000000000020 /* read */
+#define LDC_MTE_READ 0x0000000000000010 /* write */
+#define LDC_MTE_SZALL 0x000000000000000f /* page size bits */
+#define LDC_MTE_SZ16GB 0x0000000000000007 /* 16GB page */
+#define LDC_MTE_SZ2GB 0x0000000000000006 /* 2GB page */
+#define LDC_MTE_SZ256MB 0x0000000000000005 /* 256MB page */
+#define LDC_MTE_SZ32MB 0x0000000000000004 /* 32MB page */
+#define LDC_MTE_SZ4MB 0x0000000000000003 /* 4MB page */
+#define LDC_MTE_SZ512K 0x0000000000000002 /* 512K page */
+#define LDC_MTE_SZ64K 0x0000000000000001 /* 64K page */
+#define LDC_MTE_SZ8K 0x0000000000000000 /* 8K page */
+
+#ifndef __ASSEMBLY__
+struct ldc_mtable_entry {
+ unsigned long mte;
+ unsigned long cookie;
+};
+#endif
+
+/* ldc_set_map_table()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_LDC_SET_MAP_TABLE
+ * ARG0: channel ID
+ * ARG1: table real address
+ * ARG2: num entries
+ * RET0: status
+ *
+ * Register the MTE table at the given table real address, with the
+ * specified num entries, for the LDC indicated by the given channel
+ * ID.
+ */
+#define HV_FAST_LDC_SET_MAP_TABLE 0xea
+
+/* ldc_get_map_table()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_LDC_GET_MAP_TABLE
+ * ARG0: channel ID
+ * RET0: status
+ * RET1: table real address
+ * RET2: num entries
+ *
+ * Return the configuration of the current mapping table registered
+ * for the given channel ID.
+ */
+#define HV_FAST_LDC_GET_MAP_TABLE 0xeb
+
+#define LDC_COPY_IN 0
+#define LDC_COPY_OUT 1
+
+/* ldc_copy()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_LDC_COPY
+ * ARG0: channel ID
+ * ARG1: LDC_COPY_* direction code
+ * ARG2: target real address
+ * ARG3: local real address
+ * ARG4: length in bytes
+ * RET0: status
+ * RET1: actual length in bytes
+ */
+#define HV_FAST_LDC_COPY 0xec
+
+#define LDC_MEM_READ 1
+#define LDC_MEM_WRITE 2
+#define LDC_MEM_EXEC 4
+
+/* ldc_mapin()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_LDC_MAPIN
+ * ARG0: channel ID
+ * ARG1: cookie
+ * RET0: status
+ * RET1: real address
+ * RET2: LDC_MEM_* permissions
+ */
+#define HV_FAST_LDC_MAPIN 0xed
+
+/* ldc_unmap()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_LDC_UNMAP
+ * ARG0: real address
+ * RET0: status
+ */
+#define HV_FAST_LDC_UNMAP 0xee
+
+/* ldc_revoke()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_LDC_REVOKE
+ * ARG0: channel ID
+ * ARG1: cookie
+ * ARG2: ldc_mtable_entry cookie
+ * RET0: status
+ */
+#define HV_FAST_LDC_REVOKE 0xef
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_ldc_tx_qconf(unsigned long channel,
+ unsigned long ra,
+ unsigned long num_entries);
+unsigned long sun4v_ldc_tx_qinfo(unsigned long channel,
+ unsigned long *ra,
+ unsigned long *num_entries);
+unsigned long sun4v_ldc_tx_get_state(unsigned long channel,
+ unsigned long *head_off,
+ unsigned long *tail_off,
+ unsigned long *chan_state);
+unsigned long sun4v_ldc_tx_set_qtail(unsigned long channel,
+ unsigned long tail_off);
+unsigned long sun4v_ldc_rx_qconf(unsigned long channel,
+ unsigned long ra,
+ unsigned long num_entries);
+unsigned long sun4v_ldc_rx_qinfo(unsigned long channel,
+ unsigned long *ra,
+ unsigned long *num_entries);
+unsigned long sun4v_ldc_rx_get_state(unsigned long channel,
+ unsigned long *head_off,
+ unsigned long *tail_off,
+ unsigned long *chan_state);
+unsigned long sun4v_ldc_rx_set_qhead(unsigned long channel,
+ unsigned long head_off);
+unsigned long sun4v_ldc_set_map_table(unsigned long channel,
+ unsigned long ra,
+ unsigned long num_entries);
+unsigned long sun4v_ldc_get_map_table(unsigned long channel,
+ unsigned long *ra,
+ unsigned long *num_entries);
+unsigned long sun4v_ldc_copy(unsigned long channel,
+ unsigned long dir_code,
+ unsigned long tgt_raddr,
+ unsigned long lcl_raddr,
+ unsigned long len,
+ unsigned long *actual_len);
+unsigned long sun4v_ldc_mapin(unsigned long channel,
+ unsigned long cookie,
+ unsigned long *ra,
+ unsigned long *perm);
+unsigned long sun4v_ldc_unmap(unsigned long ra);
+unsigned long sun4v_ldc_revoke(unsigned long channel,
+ unsigned long cookie,
+ unsigned long mte_cookie);
+#endif
+
+/* Performance counter services. */
+
+#define HV_PERF_JBUS_PERF_CTRL_REG 0x00
+#define HV_PERF_JBUS_PERF_CNT_REG 0x01
+#define HV_PERF_DRAM_PERF_CTRL_REG_0 0x02
+#define HV_PERF_DRAM_PERF_CNT_REG_0 0x03
+#define HV_PERF_DRAM_PERF_CTRL_REG_1 0x04
+#define HV_PERF_DRAM_PERF_CNT_REG_1 0x05
+#define HV_PERF_DRAM_PERF_CTRL_REG_2 0x06
+#define HV_PERF_DRAM_PERF_CNT_REG_2 0x07
+#define HV_PERF_DRAM_PERF_CTRL_REG_3 0x08
+#define HV_PERF_DRAM_PERF_CNT_REG_3 0x09
+
+/* get_perfreg()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_GET_PERFREG
+ * ARG0: performance reg number
+ * RET0: status
+ * RET1: performance reg value
+ * ERRORS: EINVAL Invalid performance register number
+ * ENOACCESS No access allowed to performance counters
+ *
+ * Read the value of the given DRAM/JBUS performance counter/control register.
+ */
+#define HV_FAST_GET_PERFREG 0x100
+
+/* set_perfreg()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_SET_PERFREG
+ * ARG0: performance reg number
+ * ARG1: performance reg value
+ * RET0: status
+ * ERRORS: EINVAL Invalid performance register number
+ * ENOACCESS No access allowed to performance counters
+ *
+ * Write the given performance reg value to the given DRAM/JBUS
+ * performance counter/control register.
+ */
+#define HV_FAST_SET_PERFREG 0x101
+
+#define HV_N2_PERF_SPARC_CTL 0x0
+#define HV_N2_PERF_DRAM_CTL0 0x1
+#define HV_N2_PERF_DRAM_CNT0 0x2
+#define HV_N2_PERF_DRAM_CTL1 0x3
+#define HV_N2_PERF_DRAM_CNT1 0x4
+#define HV_N2_PERF_DRAM_CTL2 0x5
+#define HV_N2_PERF_DRAM_CNT2 0x6
+#define HV_N2_PERF_DRAM_CTL3 0x7
+#define HV_N2_PERF_DRAM_CNT3 0x8
+
+#define HV_FAST_N2_GET_PERFREG 0x104
+#define HV_FAST_N2_SET_PERFREG 0x105
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_niagara_getperf(unsigned long reg,
+ unsigned long *val);
+unsigned long sun4v_niagara_setperf(unsigned long reg,
+ unsigned long val);
+unsigned long sun4v_niagara2_getperf(unsigned long reg,
+ unsigned long *val);
+unsigned long sun4v_niagara2_setperf(unsigned long reg,
+ unsigned long val);
+#endif
+
+/* MMU statistics services.
+ *
+ * The hypervisor maintains MMU statistics and privileged code provides
+ * a buffer where these statistics can be collected. It is continually
+ * updated once configured. The layout is as follows:
+ */
+#ifndef __ASSEMBLY__
+struct hv_mmu_statistics {
+ unsigned long immu_tsb_hits_ctx0_8k_tte;
+ unsigned long immu_tsb_ticks_ctx0_8k_tte;
+ unsigned long immu_tsb_hits_ctx0_64k_tte;
+ unsigned long immu_tsb_ticks_ctx0_64k_tte;
+ unsigned long __reserved1[2];
+ unsigned long immu_tsb_hits_ctx0_4mb_tte;
+ unsigned long immu_tsb_ticks_ctx0_4mb_tte;
+ unsigned long __reserved2[2];
+ unsigned long immu_tsb_hits_ctx0_256mb_tte;
+ unsigned long immu_tsb_ticks_ctx0_256mb_tte;
+ unsigned long __reserved3[4];
+ unsigned long immu_tsb_hits_ctxnon0_8k_tte;
+ unsigned long immu_tsb_ticks_ctxnon0_8k_tte;
+ unsigned long immu_tsb_hits_ctxnon0_64k_tte;
+ unsigned long immu_tsb_ticks_ctxnon0_64k_tte;
+ unsigned long __reserved4[2];
+ unsigned long immu_tsb_hits_ctxnon0_4mb_tte;
+ unsigned long immu_tsb_ticks_ctxnon0_4mb_tte;
+ unsigned long __reserved5[2];
+ unsigned long immu_tsb_hits_ctxnon0_256mb_tte;
+ unsigned long immu_tsb_ticks_ctxnon0_256mb_tte;
+ unsigned long __reserved6[4];
+ unsigned long dmmu_tsb_hits_ctx0_8k_tte;
+ unsigned long dmmu_tsb_ticks_ctx0_8k_tte;
+ unsigned long dmmu_tsb_hits_ctx0_64k_tte;
+ unsigned long dmmu_tsb_ticks_ctx0_64k_tte;
+ unsigned long __reserved7[2];
+ unsigned long dmmu_tsb_hits_ctx0_4mb_tte;
+ unsigned long dmmu_tsb_ticks_ctx0_4mb_tte;
+ unsigned long __reserved8[2];
+ unsigned long dmmu_tsb_hits_ctx0_256mb_tte;
+ unsigned long dmmu_tsb_ticks_ctx0_256mb_tte;
+ unsigned long __reserved9[4];
+ unsigned long dmmu_tsb_hits_ctxnon0_8k_tte;
+ unsigned long dmmu_tsb_ticks_ctxnon0_8k_tte;
+ unsigned long dmmu_tsb_hits_ctxnon0_64k_tte;
+ unsigned long dmmu_tsb_ticks_ctxnon0_64k_tte;
+ unsigned long __reserved10[2];
+ unsigned long dmmu_tsb_hits_ctxnon0_4mb_tte;
+ unsigned long dmmu_tsb_ticks_ctxnon0_4mb_tte;
+ unsigned long __reserved11[2];
+ unsigned long dmmu_tsb_hits_ctxnon0_256mb_tte;
+ unsigned long dmmu_tsb_ticks_ctxnon0_256mb_tte;
+ unsigned long __reserved12[4];
+};
+#endif
+
+/* mmustat_conf()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MMUSTAT_CONF
+ * ARG0: real address
+ * RET0: status
+ * RET1: real address
+ * ERRORS: ENORADDR Invalid real address
+ * EBADALIGN Real address not aligned on 64-byte boundary
+ * EBADTRAP API not supported on this processor
+ *
+ * Enable MMU statistic gathering using the buffer at the given real
+ * address on the current virtual CPU. The new buffer real address
+ * is given in ARG1, and the previously specified buffer real address
+ * is returned in RET1, or is returned as zero for the first invocation.
+ *
+ * If the passed in real address argument is zero, this will disable
+ * MMU statistic collection on the current virtual CPU. If an error is
+ * returned then no statistics are collected.
+ *
+ * The buffer contents should be initialized to all zeros before being
+ * given to the hypervisor or else the statistics will be meaningless.
+ */
+#define HV_FAST_MMUSTAT_CONF 0x102
+
+/* mmustat_info()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MMUSTAT_INFO
+ * RET0: status
+ * RET1: real address
+ * ERRORS: EBADTRAP API not supported on this processor
+ *
+ * Return the current state and real address of the currently configured
+ * MMU statistics buffer on the current virtual CPU.
+ */
+#define HV_FAST_MMUSTAT_INFO 0x103
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_mmustat_conf(unsigned long ra, unsigned long *orig_ra);
+unsigned long sun4v_mmustat_info(unsigned long *ra);
+#endif
+
+/* NCS crypto services */
+
+/* ncs_request() sub-function numbers */
+#define HV_NCS_QCONF 0x01
+#define HV_NCS_QTAIL_UPDATE 0x02
+
+#ifndef __ASSEMBLY__
+struct hv_ncs_queue_entry {
+ /* MAU Control Register */
+ unsigned long mau_control;
+#define MAU_CONTROL_INV_PARITY 0x0000000000002000
+#define MAU_CONTROL_STRAND 0x0000000000001800
+#define MAU_CONTROL_BUSY 0x0000000000000400
+#define MAU_CONTROL_INT 0x0000000000000200
+#define MAU_CONTROL_OP 0x00000000000001c0
+#define MAU_CONTROL_OP_SHIFT 6
+#define MAU_OP_LOAD_MA_MEMORY 0x0
+#define MAU_OP_STORE_MA_MEMORY 0x1
+#define MAU_OP_MODULAR_MULT 0x2
+#define MAU_OP_MODULAR_REDUCE 0x3
+#define MAU_OP_MODULAR_EXP_LOOP 0x4
+#define MAU_CONTROL_LEN 0x000000000000003f
+#define MAU_CONTROL_LEN_SHIFT 0
+
+ /* Real address of bytes to load or store bytes
+ * into/out-of the MAU.
+ */
+ unsigned long mau_mpa;
+
+ /* Modular Arithmetic MA Offset Register. */
+ unsigned long mau_ma;
+
+ /* Modular Arithmetic N Prime Register. */
+ unsigned long mau_np;
+};
+
+struct hv_ncs_qconf_arg {
+ unsigned long mid; /* MAU ID, 1 per core on Niagara */
+ unsigned long base; /* Real address base of queue */
+ unsigned long end; /* Real address end of queue */
+ unsigned long num_ents; /* Number of entries in queue */
+};
+
+struct hv_ncs_qtail_update_arg {
+ unsigned long mid; /* MAU ID, 1 per core on Niagara */
+ unsigned long tail; /* New tail index to use */
+ unsigned long syncflag; /* only SYNCFLAG_SYNC is implemented */
+#define HV_NCS_SYNCFLAG_SYNC 0x00
+#define HV_NCS_SYNCFLAG_ASYNC 0x01
+};
+#endif
+
+/* ncs_request()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_NCS_REQUEST
+ * ARG0: NCS sub-function
+ * ARG1: sub-function argument real address
+ * ARG2: size in bytes of sub-function argument
+ * RET0: status
+ *
+ * The MAU chip of the Niagara processor is not directly accessible
+ * to privileged code, instead it is programmed indirectly via this
+ * hypervisor API.
+ *
+ * The interfaces defines a queue of MAU operations to perform.
+ * Privileged code registers a queue with the hypervisor by invoking
+ * this HVAPI with the HV_NCS_QCONF sub-function, which defines the
+ * base, end, and number of entries of the queue. Each queue entry
+ * contains a MAU register struct block.
+ *
+ * The privileged code then proceeds to add entries to the queue and
+ * then invoke the HV_NCS_QTAIL_UPDATE sub-function. Since only
+ * synchronous operations are supported by the current hypervisor,
+ * HV_NCS_QTAIL_UPDATE will run all the pending queue entries to
+ * completion and return HV_EOK, or return an error code.
+ *
+ * The real address of the sub-function argument must be aligned on at
+ * least an 8-byte boundary.
+ *
+ * The tail argument of HV_NCS_QTAIL_UPDATE is an index, not a byte
+ * offset, into the queue and must be less than or equal the 'num_ents'
+ * argument given in the HV_NCS_QCONF call.
+ */
+#define HV_FAST_NCS_REQUEST 0x110
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_ncs_request(unsigned long request,
+ unsigned long arg_ra,
+ unsigned long arg_size);
+#endif
+
+#define HV_FAST_FIRE_GET_PERFREG 0x120
+#define HV_FAST_FIRE_SET_PERFREG 0x121
+
+#define HV_FAST_REBOOT_DATA_SET 0x172
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_reboot_data_set(unsigned long ra,
+ unsigned long len);
+#endif
+
+#define HV_FAST_VT_GET_PERFREG 0x184
+#define HV_FAST_VT_SET_PERFREG 0x185
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_vt_get_perfreg(unsigned long reg_num,
+ unsigned long *reg_val);
+unsigned long sun4v_vt_set_perfreg(unsigned long reg_num,
+ unsigned long reg_val);
+#endif
+
+/* Function numbers for HV_CORE_TRAP. */
+#define HV_CORE_SET_VER 0x00
+#define HV_CORE_PUTCHAR 0x01
+#define HV_CORE_EXIT 0x02
+#define HV_CORE_GET_VER 0x03
+
+/* Hypervisor API groups for use with HV_CORE_SET_VER and
+ * HV_CORE_GET_VER.
+ */
+#define HV_GRP_SUN4V 0x0000
+#define HV_GRP_CORE 0x0001
+#define HV_GRP_INTR 0x0002
+#define HV_GRP_SOFT_STATE 0x0003
+#define HV_GRP_TM 0x0080
+#define HV_GRP_PCI 0x0100
+#define HV_GRP_LDOM 0x0101
+#define HV_GRP_SVC_CHAN 0x0102
+#define HV_GRP_NCS 0x0103
+#define HV_GRP_RNG 0x0104
+#define HV_GRP_PBOOT 0x0105
+#define HV_GRP_TPM 0x0107
+#define HV_GRP_SDIO 0x0108
+#define HV_GRP_SDIO_ERR 0x0109
+#define HV_GRP_REBOOT_DATA 0x0110
+#define HV_GRP_NIAG_PERF 0x0200
+#define HV_GRP_FIRE_PERF 0x0201
+#define HV_GRP_N2_CPU 0x0202
+#define HV_GRP_NIU 0x0204
+#define HV_GRP_VF_CPU 0x0205
+#define HV_GRP_KT_CPU 0x0209
+#define HV_GRP_VT_CPU 0x020c
+#define HV_GRP_DIAG 0x0300
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_get_version(unsigned long group,
+ unsigned long *major,
+ unsigned long *minor);
+unsigned long sun4v_set_version(unsigned long group,
+ unsigned long major,
+ unsigned long minor,
+ unsigned long *actual_minor);
+
+int sun4v_hvapi_register(unsigned long group, unsigned long major,
+ unsigned long *minor);
+void sun4v_hvapi_unregister(unsigned long group);
+int sun4v_hvapi_get(unsigned long group,
+ unsigned long *major,
+ unsigned long *minor);
+void sun4v_hvapi_init(void);
+#endif
+
+#endif /* !(_SPARC64_HYPERVISOR_H) */
diff --git a/arch/sparc/include/asm/ide.h b/arch/sparc/include/asm/ide.h
new file mode 100644
index 00000000000..b7af3d65823
--- /dev/null
+++ b/arch/sparc/include/asm/ide.h
@@ -0,0 +1,97 @@
+/* ide.h: SPARC PCI specific IDE glue.
+ *
+ * Copyright (C) 1997 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
+ * Adaptation from sparc64 version to sparc by Pete Zaitcev.
+ */
+
+#ifndef _SPARC_IDE_H
+#define _SPARC_IDE_H
+
+#ifdef __KERNEL__
+
+#include <asm/io.h>
+#ifdef CONFIG_SPARC64
+#include <asm/pgalloc.h>
+#include <asm/spitfire.h>
+#include <asm/cacheflush.h>
+#include <asm/page.h>
+#else
+#include <asm/pgtable.h>
+#include <asm/psr.h>
+#endif
+
+#define __ide_insl(data_reg, buffer, wcount) \
+ __ide_insw(data_reg, buffer, (wcount)<<1)
+#define __ide_outsl(data_reg, buffer, wcount) \
+ __ide_outsw(data_reg, buffer, (wcount)<<1)
+
+/* On sparc, I/O ports and MMIO registers are accessed identically. */
+#define __ide_mm_insw __ide_insw
+#define __ide_mm_insl __ide_insl
+#define __ide_mm_outsw __ide_outsw
+#define __ide_mm_outsl __ide_outsl
+
+static inline void __ide_insw(void __iomem *port, void *dst, u32 count)
+{
+#if defined(CONFIG_SPARC64) && defined(DCACHE_ALIASING_POSSIBLE)
+ unsigned long end = (unsigned long)dst + (count << 1);
+#endif
+ u16 *ps = dst;
+ u32 *pi;
+
+ if(((unsigned long)ps) & 0x2) {
+ *ps++ = __raw_readw(port);
+ count--;
+ }
+ pi = (u32 *)ps;
+ while(count >= 2) {
+ u32 w;
+
+ w = __raw_readw(port) << 16;
+ w |= __raw_readw(port);
+ *pi++ = w;
+ count -= 2;
+ }
+ ps = (u16 *)pi;
+ if(count)
+ *ps++ = __raw_readw(port);
+
+#if defined(CONFIG_SPARC64) && defined(DCACHE_ALIASING_POSSIBLE)
+ __flush_dcache_range((unsigned long)dst, end);
+#endif
+}
+
+static inline void __ide_outsw(void __iomem *port, const void *src, u32 count)
+{
+#if defined(CONFIG_SPARC64) && defined(DCACHE_ALIASING_POSSIBLE)
+ unsigned long end = (unsigned long)src + (count << 1);
+#endif
+ const u16 *ps = src;
+ const u32 *pi;
+
+ if(((unsigned long)src) & 0x2) {
+ __raw_writew(*ps++, port);
+ count--;
+ }
+ pi = (const u32 *)ps;
+ while(count >= 2) {
+ u32 w;
+
+ w = *pi++;
+ __raw_writew((w >> 16), port);
+ __raw_writew(w, port);
+ count -= 2;
+ }
+ ps = (const u16 *)pi;
+ if(count)
+ __raw_writew(*ps, port);
+
+#if defined(CONFIG_SPARC64) && defined(DCACHE_ALIASING_POSSIBLE)
+ __flush_dcache_range((unsigned long)src, end);
+#endif
+}
+
+#endif /* __KERNEL__ */
+
+#endif /* _SPARC_IDE_H */
diff --git a/arch/sparc/include/asm/idprom.h b/arch/sparc/include/asm/idprom.h
new file mode 100644
index 00000000000..3793f7f91c4
--- /dev/null
+++ b/arch/sparc/include/asm/idprom.h
@@ -0,0 +1,25 @@
+/*
+ * idprom.h: Macros and defines for idprom routines
+ *
+ * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _SPARC_IDPROM_H
+#define _SPARC_IDPROM_H
+
+#include <linux/types.h>
+
+struct idprom {
+ u8 id_format; /* Format identifier (always 0x01) */
+ u8 id_machtype; /* Machine type */
+ u8 id_ethaddr[6]; /* Hardware ethernet address */
+ s32 id_date; /* Date of manufacture */
+ u32 id_sernum:24; /* Unique serial number */
+ u8 id_cksum; /* Checksum - xor of the data bytes */
+ u8 reserved[16];
+};
+
+extern struct idprom *idprom;
+void idprom_init(void);
+
+#endif /* !(_SPARC_IDPROM_H) */
diff --git a/arch/sparc/include/asm/intr_queue.h b/arch/sparc/include/asm/intr_queue.h
new file mode 100644
index 00000000000..206077dedc2
--- /dev/null
+++ b/arch/sparc/include/asm/intr_queue.h
@@ -0,0 +1,15 @@
+#ifndef _SPARC64_INTR_QUEUE_H
+#define _SPARC64_INTR_QUEUE_H
+
+/* Sun4v interrupt queue registers, accessed via ASI_QUEUE. */
+
+#define INTRQ_CPU_MONDO_HEAD 0x3c0 /* CPU mondo head */
+#define INTRQ_CPU_MONDO_TAIL 0x3c8 /* CPU mondo tail */
+#define INTRQ_DEVICE_MONDO_HEAD 0x3d0 /* Device mondo head */
+#define INTRQ_DEVICE_MONDO_TAIL 0x3d8 /* Device mondo tail */
+#define INTRQ_RESUM_MONDO_HEAD 0x3e0 /* Resumable error mondo head */
+#define INTRQ_RESUM_MONDO_TAIL 0x3e8 /* Resumable error mondo tail */
+#define INTRQ_NONRESUM_MONDO_HEAD 0x3f0 /* Non-resumable error mondo head */
+#define INTRQ_NONRESUM_MONDO_TAIL 0x3f8 /* Non-resumable error mondo head */
+
+#endif /* !(_SPARC64_INTR_QUEUE_H) */
diff --git a/arch/sparc/include/asm/io-unit.h b/arch/sparc/include/asm/io-unit.h
new file mode 100644
index 00000000000..04a9701e720
--- /dev/null
+++ b/arch/sparc/include/asm/io-unit.h
@@ -0,0 +1,58 @@
+/* io-unit.h: Definitions for the sun4d IO-UNIT.
+ *
+ * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+#ifndef _SPARC_IO_UNIT_H
+#define _SPARC_IO_UNIT_H
+
+#include <linux/spinlock.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+/* The io-unit handles all virtual to physical address translations
+ * that occur between the SBUS and physical memory. Access by
+ * the cpu to IO registers and similar go over the xdbus so are
+ * translated by the on chip SRMMU. The io-unit and the srmmu do
+ * not need to have the same translations at all, in fact most
+ * of the time the translations they handle are a disjunct set.
+ * Basically the io-unit handles all dvma sbus activity.
+ */
+
+/* AIEEE, unlike the nice sun4m, these monsters have
+ fixed DMA range 64M */
+
+#define IOUNIT_DMA_BASE 0xfc000000 /* TOP - 64M */
+#define IOUNIT_DMA_SIZE 0x04000000 /* 64M */
+/* We use last 1M for sparc_dvma_malloc */
+#define IOUNIT_DVMA_SIZE 0x00100000 /* 1M */
+
+/* The format of an iopte in the external page tables */
+#define IOUPTE_PAGE 0xffffff00 /* Physical page number (PA[35:12]) */
+#define IOUPTE_CACHE 0x00000080 /* Cached (in Viking/MXCC) */
+/* XXX Jakub, find out how to program SBUS streaming cache on XDBUS/sun4d.
+ * XXX Actually, all you should need to do is find out where the registers
+ * XXX are and copy over the sparc64 implementation I wrote. There may be
+ * XXX some horrible hwbugs though, so be careful. -DaveM
+ */
+#define IOUPTE_STREAM 0x00000040 /* Translation can use streaming cache */
+#define IOUPTE_INTRA 0x00000008 /* SBUS direct slot->slot transfer */
+#define IOUPTE_WRITE 0x00000004 /* Writeable */
+#define IOUPTE_VALID 0x00000002 /* IOPTE is valid */
+#define IOUPTE_PARITY 0x00000001 /* Parity is checked during DVMA */
+
+struct iounit_struct {
+ unsigned long bmap[(IOUNIT_DMA_SIZE >> (PAGE_SHIFT + 3)) / sizeof(unsigned long)];
+ spinlock_t lock;
+ iopte_t __iomem *page_table;
+ unsigned long rotor[3];
+ unsigned long limit[4];
+};
+
+#define IOUNIT_BMAP1_START 0x00000000
+#define IOUNIT_BMAP1_END (IOUNIT_DMA_SIZE >> (PAGE_SHIFT + 1))
+#define IOUNIT_BMAP2_START IOUNIT_BMAP1_END
+#define IOUNIT_BMAP2_END IOUNIT_BMAP2_START + (IOUNIT_DMA_SIZE >> (PAGE_SHIFT + 2))
+#define IOUNIT_BMAPM_START IOUNIT_BMAP2_END
+#define IOUNIT_BMAPM_END ((IOUNIT_DMA_SIZE - IOUNIT_DVMA_SIZE) >> PAGE_SHIFT)
+
+#endif /* !(_SPARC_IO_UNIT_H) */
diff --git a/arch/sparc/include/asm/io.h b/arch/sparc/include/asm/io.h
new file mode 100644
index 00000000000..f6902cf3cbe
--- /dev/null
+++ b/arch/sparc/include/asm/io.h
@@ -0,0 +1,21 @@
+#ifndef ___ASM_SPARC_IO_H
+#define ___ASM_SPARC_IO_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/io_64.h>
+#else
+#include <asm/io_32.h>
+#endif
+
+/*
+ * Defines used for both SPARC32 and SPARC64
+ */
+
+/* Big endian versions of memory read/write routines */
+#define readb_be(__addr) __raw_readb(__addr)
+#define readw_be(__addr) __raw_readw(__addr)
+#define readl_be(__addr) __raw_readl(__addr)
+#define writeb_be(__b, __addr) __raw_writeb(__b, __addr)
+#define writel_be(__w, __addr) __raw_writel(__w, __addr)
+#define writew_be(__l, __addr) __raw_writew(__l, __addr)
+
+#endif
diff --git a/arch/sparc/include/asm/io_32.h b/arch/sparc/include/asm/io_32.h
new file mode 100644
index 00000000000..9f532902627
--- /dev/null
+++ b/arch/sparc/include/asm/io_32.h
@@ -0,0 +1,172 @@
+#ifndef __SPARC_IO_H
+#define __SPARC_IO_H
+
+#include <linux/kernel.h>
+#include <linux/ioport.h> /* struct resource */
+
+#define readb_relaxed(__addr) readb(__addr)
+#define readw_relaxed(__addr) readw(__addr)
+#define readl_relaxed(__addr) readl(__addr)
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+#define memset_io(d,c,sz) _memset_io(d,c,sz)
+#define memcpy_fromio(d,s,sz) _memcpy_fromio(d,s,sz)
+#define memcpy_toio(d,s,sz) _memcpy_toio(d,s,sz)
+
+#include <asm-generic/io.h>
+
+static inline void _memset_io(volatile void __iomem *dst,
+ int c, __kernel_size_t n)
+{
+ volatile void __iomem *d = dst;
+
+ while (n--) {
+ writeb(c, d);
+ d++;
+ }
+}
+
+static inline void _memcpy_fromio(void *dst, const volatile void __iomem *src,
+ __kernel_size_t n)
+{
+ char *d = dst;
+
+ while (n--) {
+ char tmp = readb(src);
+ *d++ = tmp;
+ src++;
+ }
+}
+
+static inline void _memcpy_toio(volatile void __iomem *dst, const void *src,
+ __kernel_size_t n)
+{
+ const char *s = src;
+ volatile void __iomem *d = dst;
+
+ while (n--) {
+ char tmp = *s++;
+ writeb(tmp, d);
+ d++;
+ }
+}
+
+/*
+ * SBus accessors.
+ *
+ * SBus has only one, memory mapped, I/O space.
+ * We do not need to flip bytes for SBus of course.
+ */
+static inline u8 sbus_readb(const volatile void __iomem *addr)
+{
+ return *(__force volatile u8 *)addr;
+}
+
+static inline u16 sbus_readw(const volatile void __iomem *addr)
+{
+ return *(__force volatile u16 *)addr;
+}
+
+static inline u32 sbus_readl(const volatile void __iomem *addr)
+{
+ return *(__force volatile u32 *)addr;
+}
+
+static inline void sbus_writeb(u8 b, volatile void __iomem *addr)
+{
+ *(__force volatile u8 *)addr = b;
+}
+
+static inline void sbus_writew(u16 w, volatile void __iomem *addr)
+{
+ *(__force volatile u16 *)addr = w;
+}
+
+static inline void sbus_writel(u32 l, volatile void __iomem *addr)
+{
+ *(__force volatile u32 *)addr = l;
+}
+
+static inline void sbus_memset_io(volatile void __iomem *__dst, int c,
+ __kernel_size_t n)
+{
+ while(n--) {
+ sbus_writeb(c, __dst);
+ __dst++;
+ }
+}
+
+static inline void sbus_memcpy_fromio(void *dst,
+ const volatile void __iomem *src,
+ __kernel_size_t n)
+{
+ char *d = dst;
+
+ while (n--) {
+ char tmp = sbus_readb(src);
+ *d++ = tmp;
+ src++;
+ }
+}
+
+static inline void sbus_memcpy_toio(volatile void __iomem *dst,
+ const void *src,
+ __kernel_size_t n)
+{
+ const char *s = src;
+ volatile void __iomem *d = dst;
+
+ while (n--) {
+ char tmp = *s++;
+ sbus_writeb(tmp, d);
+ d++;
+ }
+}
+
+#ifdef __KERNEL__
+
+/*
+ * Bus number may be embedded in the higher bits of the physical address.
+ * This is why we have no bus number argument to ioremap().
+ */
+void __iomem *ioremap(unsigned long offset, unsigned long size);
+#define ioremap_nocache(X,Y) ioremap((X),(Y))
+#define ioremap_wc(X,Y) ioremap((X),(Y))
+void iounmap(volatile void __iomem *addr);
+
+/* Create a virtual mapping cookie for an IO port range */
+void __iomem *ioport_map(unsigned long port, unsigned int nr);
+void ioport_unmap(void __iomem *);
+
+/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
+struct pci_dev;
+void pci_iounmap(struct pci_dev *dev, void __iomem *);
+
+
+
+/*
+ * At the moment, we do not use CMOS_READ anywhere outside of rtc.c,
+ * so rtc_port is static in it. This should not change unless a new
+ * hardware pops up.
+ */
+#define RTC_PORT(x) (rtc_port + (x))
+#define RTC_ALWAYS_BCD 0
+
+static inline int sbus_can_dma_64bit(void)
+{
+ return 0; /* actually, sparc_cpu_model==sun4d */
+}
+static inline int sbus_can_burst64(void)
+{
+ return 0; /* actually, sparc_cpu_model==sun4d */
+}
+struct device;
+void sbus_set_sbus64(struct device *, int);
+
+#endif
+
+#define __ARCH_HAS_NO_PAGE_ZERO_MAPPED 1
+
+
+#endif /* !(__SPARC_IO_H) */
diff --git a/arch/sparc/include/asm/io_64.h b/arch/sparc/include/asm/io_64.h
new file mode 100644
index 00000000000..05381c3a422
--- /dev/null
+++ b/arch/sparc/include/asm/io_64.h
@@ -0,0 +1,542 @@
+#ifndef __SPARC64_IO_H
+#define __SPARC64_IO_H
+
+#include <linux/kernel.h>
+#include <linux/compiler.h>
+#include <linux/types.h>
+
+#include <asm/page.h> /* IO address mapping routines need this */
+#include <asm/asi.h>
+#include <asm-generic/pci_iomap.h>
+
+/* PC crapola... */
+#define __SLOW_DOWN_IO do { } while (0)
+#define SLOW_DOWN_IO do { } while (0)
+
+/* BIO layer definitions. */
+extern unsigned long kern_base, kern_size;
+
+static inline u8 _inb(unsigned long addr)
+{
+ u8 ret;
+
+ __asm__ __volatile__("lduba\t[%1] %2, %0\t/* pci_inb */"
+ : "=r" (ret)
+ : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+ : "memory");
+
+ return ret;
+}
+
+static inline u16 _inw(unsigned long addr)
+{
+ u16 ret;
+
+ __asm__ __volatile__("lduha\t[%1] %2, %0\t/* pci_inw */"
+ : "=r" (ret)
+ : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+ : "memory");
+
+ return ret;
+}
+
+static inline u32 _inl(unsigned long addr)
+{
+ u32 ret;
+
+ __asm__ __volatile__("lduwa\t[%1] %2, %0\t/* pci_inl */"
+ : "=r" (ret)
+ : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+ : "memory");
+
+ return ret;
+}
+
+static inline void _outb(u8 b, unsigned long addr)
+{
+ __asm__ __volatile__("stba\t%r0, [%1] %2\t/* pci_outb */"
+ : /* no outputs */
+ : "Jr" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+ : "memory");
+}
+
+static inline void _outw(u16 w, unsigned long addr)
+{
+ __asm__ __volatile__("stha\t%r0, [%1] %2\t/* pci_outw */"
+ : /* no outputs */
+ : "Jr" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+ : "memory");
+}
+
+static inline void _outl(u32 l, unsigned long addr)
+{
+ __asm__ __volatile__("stwa\t%r0, [%1] %2\t/* pci_outl */"
+ : /* no outputs */
+ : "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+ : "memory");
+}
+
+#define inb(__addr) (_inb((unsigned long)(__addr)))
+#define inw(__addr) (_inw((unsigned long)(__addr)))
+#define inl(__addr) (_inl((unsigned long)(__addr)))
+#define outb(__b, __addr) (_outb((u8)(__b), (unsigned long)(__addr)))
+#define outw(__w, __addr) (_outw((u16)(__w), (unsigned long)(__addr)))
+#define outl(__l, __addr) (_outl((u32)(__l), (unsigned long)(__addr)))
+
+#define inb_p(__addr) inb(__addr)
+#define outb_p(__b, __addr) outb(__b, __addr)
+#define inw_p(__addr) inw(__addr)
+#define outw_p(__w, __addr) outw(__w, __addr)
+#define inl_p(__addr) inl(__addr)
+#define outl_p(__l, __addr) outl(__l, __addr)
+
+void outsb(unsigned long, const void *, unsigned long);
+void outsw(unsigned long, const void *, unsigned long);
+void outsl(unsigned long, const void *, unsigned long);
+void insb(unsigned long, void *, unsigned long);
+void insw(unsigned long, void *, unsigned long);
+void insl(unsigned long, void *, unsigned long);
+
+static inline void ioread8_rep(void __iomem *port, void *buf, unsigned long count)
+{
+ insb((unsigned long __force)port, buf, count);
+}
+static inline void ioread16_rep(void __iomem *port, void *buf, unsigned long count)
+{
+ insw((unsigned long __force)port, buf, count);
+}
+
+static inline void ioread32_rep(void __iomem *port, void *buf, unsigned long count)
+{
+ insl((unsigned long __force)port, buf, count);
+}
+
+static inline void iowrite8_rep(void __iomem *port, const void *buf, unsigned long count)
+{
+ outsb((unsigned long __force)port, buf, count);
+}
+
+static inline void iowrite16_rep(void __iomem *port, const void *buf, unsigned long count)
+{
+ outsw((unsigned long __force)port, buf, count);
+}
+
+static inline void iowrite32_rep(void __iomem *port, const void *buf, unsigned long count)
+{
+ outsl((unsigned long __force)port, buf, count);
+}
+
+/* Memory functions, same as I/O accesses on Ultra. */
+static inline u8 _readb(const volatile void __iomem *addr)
+{ u8 ret;
+
+ __asm__ __volatile__("lduba\t[%1] %2, %0\t/* pci_readb */"
+ : "=r" (ret)
+ : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+ : "memory");
+ return ret;
+}
+
+static inline u16 _readw(const volatile void __iomem *addr)
+{ u16 ret;
+
+ __asm__ __volatile__("lduha\t[%1] %2, %0\t/* pci_readw */"
+ : "=r" (ret)
+ : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+ : "memory");
+
+ return ret;
+}
+
+static inline u32 _readl(const volatile void __iomem *addr)
+{ u32 ret;
+
+ __asm__ __volatile__("lduwa\t[%1] %2, %0\t/* pci_readl */"
+ : "=r" (ret)
+ : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+ : "memory");
+
+ return ret;
+}
+
+static inline u64 _readq(const volatile void __iomem *addr)
+{ u64 ret;
+
+ __asm__ __volatile__("ldxa\t[%1] %2, %0\t/* pci_readq */"
+ : "=r" (ret)
+ : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+ : "memory");
+
+ return ret;
+}
+
+static inline void _writeb(u8 b, volatile void __iomem *addr)
+{
+ __asm__ __volatile__("stba\t%r0, [%1] %2\t/* pci_writeb */"
+ : /* no outputs */
+ : "Jr" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+ : "memory");
+}
+
+static inline void _writew(u16 w, volatile void __iomem *addr)
+{
+ __asm__ __volatile__("stha\t%r0, [%1] %2\t/* pci_writew */"
+ : /* no outputs */
+ : "Jr" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+ : "memory");
+}
+
+static inline void _writel(u32 l, volatile void __iomem *addr)
+{
+ __asm__ __volatile__("stwa\t%r0, [%1] %2\t/* pci_writel */"
+ : /* no outputs */
+ : "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+ : "memory");
+}
+
+static inline void _writeq(u64 q, volatile void __iomem *addr)
+{
+ __asm__ __volatile__("stxa\t%r0, [%1] %2\t/* pci_writeq */"
+ : /* no outputs */
+ : "Jr" (q), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+ : "memory");
+}
+
+#define readb(__addr) _readb(__addr)
+#define readw(__addr) _readw(__addr)
+#define readl(__addr) _readl(__addr)
+#define readq(__addr) _readq(__addr)
+#define readb_relaxed(__addr) _readb(__addr)
+#define readw_relaxed(__addr) _readw(__addr)
+#define readl_relaxed(__addr) _readl(__addr)
+#define readq_relaxed(__addr) _readq(__addr)
+#define writeb(__b, __addr) _writeb(__b, __addr)
+#define writew(__w, __addr) _writew(__w, __addr)
+#define writel(__l, __addr) _writel(__l, __addr)
+#define writeq(__q, __addr) _writeq(__q, __addr)
+
+/* Now versions without byte-swapping. */
+static inline u8 _raw_readb(unsigned long addr)
+{
+ u8 ret;
+
+ __asm__ __volatile__("lduba\t[%1] %2, %0\t/* pci_raw_readb */"
+ : "=r" (ret)
+ : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+
+ return ret;
+}
+
+static inline u16 _raw_readw(unsigned long addr)
+{
+ u16 ret;
+
+ __asm__ __volatile__("lduha\t[%1] %2, %0\t/* pci_raw_readw */"
+ : "=r" (ret)
+ : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+
+ return ret;
+}
+
+static inline u32 _raw_readl(unsigned long addr)
+{
+ u32 ret;
+
+ __asm__ __volatile__("lduwa\t[%1] %2, %0\t/* pci_raw_readl */"
+ : "=r" (ret)
+ : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+
+ return ret;
+}
+
+static inline u64 _raw_readq(unsigned long addr)
+{
+ u64 ret;
+
+ __asm__ __volatile__("ldxa\t[%1] %2, %0\t/* pci_raw_readq */"
+ : "=r" (ret)
+ : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+
+ return ret;
+}
+
+static inline void _raw_writeb(u8 b, unsigned long addr)
+{
+ __asm__ __volatile__("stba\t%r0, [%1] %2\t/* pci_raw_writeb */"
+ : /* no outputs */
+ : "Jr" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+}
+
+static inline void _raw_writew(u16 w, unsigned long addr)
+{
+ __asm__ __volatile__("stha\t%r0, [%1] %2\t/* pci_raw_writew */"
+ : /* no outputs */
+ : "Jr" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+}
+
+static inline void _raw_writel(u32 l, unsigned long addr)
+{
+ __asm__ __volatile__("stwa\t%r0, [%1] %2\t/* pci_raw_writel */"
+ : /* no outputs */
+ : "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+}
+
+static inline void _raw_writeq(u64 q, unsigned long addr)
+{
+ __asm__ __volatile__("stxa\t%r0, [%1] %2\t/* pci_raw_writeq */"
+ : /* no outputs */
+ : "Jr" (q), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+}
+
+#define __raw_readb(__addr) (_raw_readb((unsigned long)(__addr)))
+#define __raw_readw(__addr) (_raw_readw((unsigned long)(__addr)))
+#define __raw_readl(__addr) (_raw_readl((unsigned long)(__addr)))
+#define __raw_readq(__addr) (_raw_readq((unsigned long)(__addr)))
+#define __raw_writeb(__b, __addr) (_raw_writeb((u8)(__b), (unsigned long)(__addr)))
+#define __raw_writew(__w, __addr) (_raw_writew((u16)(__w), (unsigned long)(__addr)))
+#define __raw_writel(__l, __addr) (_raw_writel((u32)(__l), (unsigned long)(__addr)))
+#define __raw_writeq(__q, __addr) (_raw_writeq((u64)(__q), (unsigned long)(__addr)))
+
+/* Valid I/O Space regions are anywhere, because each PCI bus supported
+ * can live in an arbitrary area of the physical address range.
+ */
+#define IO_SPACE_LIMIT 0xffffffffffffffffUL
+
+/* Now, SBUS variants, only difference from PCI is that we do
+ * not use little-endian ASIs.
+ */
+static inline u8 _sbus_readb(const volatile void __iomem *addr)
+{
+ u8 ret;
+
+ __asm__ __volatile__("lduba\t[%1] %2, %0\t/* sbus_readb */"
+ : "=r" (ret)
+ : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
+ : "memory");
+
+ return ret;
+}
+
+static inline u16 _sbus_readw(const volatile void __iomem *addr)
+{
+ u16 ret;
+
+ __asm__ __volatile__("lduha\t[%1] %2, %0\t/* sbus_readw */"
+ : "=r" (ret)
+ : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
+ : "memory");
+
+ return ret;
+}
+
+static inline u32 _sbus_readl(const volatile void __iomem *addr)
+{
+ u32 ret;
+
+ __asm__ __volatile__("lduwa\t[%1] %2, %0\t/* sbus_readl */"
+ : "=r" (ret)
+ : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
+ : "memory");
+
+ return ret;
+}
+
+static inline u64 _sbus_readq(const volatile void __iomem *addr)
+{
+ u64 ret;
+
+ __asm__ __volatile__("ldxa\t[%1] %2, %0\t/* sbus_readq */"
+ : "=r" (ret)
+ : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
+ : "memory");
+
+ return ret;
+}
+
+static inline void _sbus_writeb(u8 b, volatile void __iomem *addr)
+{
+ __asm__ __volatile__("stba\t%r0, [%1] %2\t/* sbus_writeb */"
+ : /* no outputs */
+ : "Jr" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
+ : "memory");
+}
+
+static inline void _sbus_writew(u16 w, volatile void __iomem *addr)
+{
+ __asm__ __volatile__("stha\t%r0, [%1] %2\t/* sbus_writew */"
+ : /* no outputs */
+ : "Jr" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
+ : "memory");
+}
+
+static inline void _sbus_writel(u32 l, volatile void __iomem *addr)
+{
+ __asm__ __volatile__("stwa\t%r0, [%1] %2\t/* sbus_writel */"
+ : /* no outputs */
+ : "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
+ : "memory");
+}
+
+static inline void _sbus_writeq(u64 l, volatile void __iomem *addr)
+{
+ __asm__ __volatile__("stxa\t%r0, [%1] %2\t/* sbus_writeq */"
+ : /* no outputs */
+ : "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
+ : "memory");
+}
+
+#define sbus_readb(__addr) _sbus_readb(__addr)
+#define sbus_readw(__addr) _sbus_readw(__addr)
+#define sbus_readl(__addr) _sbus_readl(__addr)
+#define sbus_readq(__addr) _sbus_readq(__addr)
+#define sbus_writeb(__b, __addr) _sbus_writeb(__b, __addr)
+#define sbus_writew(__w, __addr) _sbus_writew(__w, __addr)
+#define sbus_writel(__l, __addr) _sbus_writel(__l, __addr)
+#define sbus_writeq(__l, __addr) _sbus_writeq(__l, __addr)
+
+static inline void _sbus_memset_io(volatile void __iomem *dst, int c, __kernel_size_t n)
+{
+ while(n--) {
+ sbus_writeb(c, dst);
+ dst++;
+ }
+}
+
+#define sbus_memset_io(d,c,sz) _sbus_memset_io(d,c,sz)
+
+static inline void
+_memset_io(volatile void __iomem *dst, int c, __kernel_size_t n)
+{
+ volatile void __iomem *d = dst;
+
+ while (n--) {
+ writeb(c, d);
+ d++;
+ }
+}
+
+#define memset_io(d,c,sz) _memset_io(d,c,sz)
+
+static inline void
+_sbus_memcpy_fromio(void *dst, const volatile void __iomem *src,
+ __kernel_size_t n)
+{
+ char *d = dst;
+
+ while (n--) {
+ char tmp = sbus_readb(src);
+ *d++ = tmp;
+ src++;
+ }
+}
+
+#define sbus_memcpy_fromio(d, s, sz) _sbus_memcpy_fromio(d, s, sz)
+
+static inline void
+_memcpy_fromio(void *dst, const volatile void __iomem *src, __kernel_size_t n)
+{
+ char *d = dst;
+
+ while (n--) {
+ char tmp = readb(src);
+ *d++ = tmp;
+ src++;
+ }
+}
+
+#define memcpy_fromio(d,s,sz) _memcpy_fromio(d,s,sz)
+
+static inline void
+_sbus_memcpy_toio(volatile void __iomem *dst, const void *src,
+ __kernel_size_t n)
+{
+ const char *s = src;
+ volatile void __iomem *d = dst;
+
+ while (n--) {
+ char tmp = *s++;
+ sbus_writeb(tmp, d);
+ d++;
+ }
+}
+
+#define sbus_memcpy_toio(d, s, sz) _sbus_memcpy_toio(d, s, sz)
+
+static inline void
+_memcpy_toio(volatile void __iomem *dst, const void *src, __kernel_size_t n)
+{
+ const char *s = src;
+ volatile void __iomem *d = dst;
+
+ while (n--) {
+ char tmp = *s++;
+ writeb(tmp, d);
+ d++;
+ }
+}
+
+#define memcpy_toio(d,s,sz) _memcpy_toio(d,s,sz)
+
+#define mmiowb()
+
+#ifdef __KERNEL__
+
+/* On sparc64 we have the whole physical IO address space accessible
+ * using physically addressed loads and stores, so this does nothing.
+ */
+static inline void __iomem *ioremap(unsigned long offset, unsigned long size)
+{
+ return (void __iomem *)offset;
+}
+
+#define ioremap_nocache(X,Y) ioremap((X),(Y))
+#define ioremap_wc(X,Y) ioremap((X),(Y))
+
+static inline void iounmap(volatile void __iomem *addr)
+{
+}
+
+#define ioread8(X) readb(X)
+#define ioread16(X) readw(X)
+#define ioread16be(X) __raw_readw(X)
+#define ioread32(X) readl(X)
+#define ioread32be(X) __raw_readl(X)
+#define iowrite8(val,X) writeb(val,X)
+#define iowrite16(val,X) writew(val,X)
+#define iowrite16be(val,X) __raw_writew(val,X)
+#define iowrite32(val,X) writel(val,X)
+#define iowrite32be(val,X) __raw_writel(val,X)
+
+/* Create a virtual mapping cookie for an IO port range */
+void __iomem *ioport_map(unsigned long port, unsigned int nr);
+void ioport_unmap(void __iomem *);
+
+/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
+struct pci_dev;
+void pci_iounmap(struct pci_dev *dev, void __iomem *);
+
+static inline int sbus_can_dma_64bit(void)
+{
+ return 1;
+}
+static inline int sbus_can_burst64(void)
+{
+ return 1;
+}
+struct device;
+void sbus_set_sbus64(struct device *, int);
+
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+#define xlate_dev_mem_ptr(p) __va(p)
+
+/*
+ * Convert a virtual cached pointer to an uncached pointer
+ */
+#define xlate_dev_kmem_ptr(p) p
+
+#endif
+
+#endif /* !(__SPARC64_IO_H) */
diff --git a/arch/sparc/include/asm/ioctls.h b/arch/sparc/include/asm/ioctls.h
new file mode 100644
index 00000000000..77413b7e3a1
--- /dev/null
+++ b/arch/sparc/include/asm/ioctls.h
@@ -0,0 +1,13 @@
+#ifndef _ASM_SPARC_IOCTLS_H
+#define _ASM_SPARC_IOCTLS_H
+
+#include <uapi/asm/ioctls.h>
+
+#define TIOCGETC __TIOCGETC
+#define TIOCGETP __TIOCGETP
+#define TIOCGLTC __TIOCGLTC
+#define TIOCSLTC __TIOCSLTC
+#define TIOCSETP __TIOCSETP
+#define TIOCSETN __TIOCSETN
+#define TIOCSETC __TIOCSETC
+#endif /* !(_ASM_SPARC_IOCTLS_H) */
diff --git a/arch/sparc/include/asm/iommu.h b/arch/sparc/include/asm/iommu.h
new file mode 100644
index 00000000000..e650965b4a8
--- /dev/null
+++ b/arch/sparc/include/asm/iommu.h
@@ -0,0 +1,8 @@
+#ifndef ___ASM_SPARC_IOMMU_H
+#define ___ASM_SPARC_IOMMU_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/iommu_64.h>
+#else
+#include <asm/iommu_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/iommu_32.h b/arch/sparc/include/asm/iommu_32.h
new file mode 100644
index 00000000000..f6c066b52fd
--- /dev/null
+++ b/arch/sparc/include/asm/iommu_32.h
@@ -0,0 +1,121 @@
+/* iommu.h: Definitions for the sun4m IOMMU.
+ *
+ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ */
+#ifndef _SPARC_IOMMU_H
+#define _SPARC_IOMMU_H
+
+#include <asm/page.h>
+#include <asm/bitext.h>
+
+/* The iommu handles all virtual to physical address translations
+ * that occur between the SBUS and physical memory. Access by
+ * the cpu to IO registers and similar go over the mbus so are
+ * translated by the on chip SRMMU. The iommu and the srmmu do
+ * not need to have the same translations at all, in fact most
+ * of the time the translations they handle are a disjunct set.
+ * Basically the iommu handles all dvma sbus activity.
+ */
+
+/* The IOMMU registers occupy three pages in IO space. */
+struct iommu_regs {
+ /* First page */
+ volatile unsigned long control; /* IOMMU control */
+ volatile unsigned long base; /* Physical base of iopte page table */
+ volatile unsigned long _unused1[3];
+ volatile unsigned long tlbflush; /* write only */
+ volatile unsigned long pageflush; /* write only */
+ volatile unsigned long _unused2[1017];
+ /* Second page */
+ volatile unsigned long afsr; /* Async-fault status register */
+ volatile unsigned long afar; /* Async-fault physical address */
+ volatile unsigned long _unused3[2];
+ volatile unsigned long sbuscfg0; /* SBUS configuration registers, per-slot */
+ volatile unsigned long sbuscfg1;
+ volatile unsigned long sbuscfg2;
+ volatile unsigned long sbuscfg3;
+ volatile unsigned long mfsr; /* Memory-fault status register */
+ volatile unsigned long mfar; /* Memory-fault physical address */
+ volatile unsigned long _unused4[1014];
+ /* Third page */
+ volatile unsigned long mid; /* IOMMU module-id */
+};
+
+#define IOMMU_CTRL_IMPL 0xf0000000 /* Implementation */
+#define IOMMU_CTRL_VERS 0x0f000000 /* Version */
+#define IOMMU_CTRL_RNGE 0x0000001c /* Mapping RANGE */
+#define IOMMU_RNGE_16MB 0x00000000 /* 0xff000000 -> 0xffffffff */
+#define IOMMU_RNGE_32MB 0x00000004 /* 0xfe000000 -> 0xffffffff */
+#define IOMMU_RNGE_64MB 0x00000008 /* 0xfc000000 -> 0xffffffff */
+#define IOMMU_RNGE_128MB 0x0000000c /* 0xf8000000 -> 0xffffffff */
+#define IOMMU_RNGE_256MB 0x00000010 /* 0xf0000000 -> 0xffffffff */
+#define IOMMU_RNGE_512MB 0x00000014 /* 0xe0000000 -> 0xffffffff */
+#define IOMMU_RNGE_1GB 0x00000018 /* 0xc0000000 -> 0xffffffff */
+#define IOMMU_RNGE_2GB 0x0000001c /* 0x80000000 -> 0xffffffff */
+#define IOMMU_CTRL_ENAB 0x00000001 /* IOMMU Enable */
+
+#define IOMMU_AFSR_ERR 0x80000000 /* LE, TO, or BE asserted */
+#define IOMMU_AFSR_LE 0x40000000 /* SBUS reports error after transaction */
+#define IOMMU_AFSR_TO 0x20000000 /* Write access took more than 12.8 us. */
+#define IOMMU_AFSR_BE 0x10000000 /* Write access received error acknowledge */
+#define IOMMU_AFSR_SIZE 0x0e000000 /* Size of transaction causing error */
+#define IOMMU_AFSR_S 0x01000000 /* Sparc was in supervisor mode */
+#define IOMMU_AFSR_RESV 0x00f00000 /* Reserver, forced to 0x8 by hardware */
+#define IOMMU_AFSR_ME 0x00080000 /* Multiple errors occurred */
+#define IOMMU_AFSR_RD 0x00040000 /* A read operation was in progress */
+#define IOMMU_AFSR_FAV 0x00020000 /* IOMMU afar has valid contents */
+
+#define IOMMU_SBCFG_SAB30 0x00010000 /* Phys-address bit 30 when bypass enabled */
+#define IOMMU_SBCFG_BA16 0x00000004 /* Slave supports 16 byte bursts */
+#define IOMMU_SBCFG_BA8 0x00000002 /* Slave supports 8 byte bursts */
+#define IOMMU_SBCFG_BYPASS 0x00000001 /* Bypass IOMMU, treat all addresses
+ produced by this device as pure
+ physical. */
+
+#define IOMMU_MFSR_ERR 0x80000000 /* One or more of PERR1 or PERR0 */
+#define IOMMU_MFSR_S 0x01000000 /* Sparc was in supervisor mode */
+#define IOMMU_MFSR_CPU 0x00800000 /* CPU transaction caused parity error */
+#define IOMMU_MFSR_ME 0x00080000 /* Multiple parity errors occurred */
+#define IOMMU_MFSR_PERR 0x00006000 /* high bit indicates parity error occurred
+ on the even word of the access, low bit
+ indicated odd word caused the parity error */
+#define IOMMU_MFSR_BM 0x00001000 /* Error occurred while in boot mode */
+#define IOMMU_MFSR_C 0x00000800 /* Address causing error was marked cacheable */
+#define IOMMU_MFSR_RTYP 0x000000f0 /* Memory request transaction type */
+
+#define IOMMU_MID_SBAE 0x001f0000 /* SBus arbitration enable */
+#define IOMMU_MID_SE 0x00100000 /* Enables SCSI/ETHERNET arbitration */
+#define IOMMU_MID_SB3 0x00080000 /* Enable SBUS device 3 arbitration */
+#define IOMMU_MID_SB2 0x00040000 /* Enable SBUS device 2 arbitration */
+#define IOMMU_MID_SB1 0x00020000 /* Enable SBUS device 1 arbitration */
+#define IOMMU_MID_SB0 0x00010000 /* Enable SBUS device 0 arbitration */
+#define IOMMU_MID_MID 0x0000000f /* Module-id, hardcoded to 0x8 */
+
+/* The format of an iopte in the page tables */
+#define IOPTE_PAGE 0x07ffff00 /* Physical page number (PA[30:12]) */
+#define IOPTE_CACHE 0x00000080 /* Cached (in vme IOCACHE or Viking/MXCC) */
+#define IOPTE_WRITE 0x00000004 /* Writeable */
+#define IOPTE_VALID 0x00000002 /* IOPTE is valid */
+#define IOPTE_WAZ 0x00000001 /* Write as zeros */
+
+struct iommu_struct {
+ struct iommu_regs __iomem *regs;
+ iopte_t *page_table;
+ /* For convenience */
+ unsigned long start; /* First managed virtual address */
+ unsigned long end; /* Last managed virtual address */
+
+ struct bit_map usemap;
+};
+
+static inline void iommu_invalidate(struct iommu_regs __iomem *regs)
+{
+ sbus_writel(0, &regs->tlbflush);
+}
+
+static inline void iommu_invalidate_page(struct iommu_regs __iomem *regs, unsigned long ba)
+{
+ sbus_writel(ba & PAGE_MASK, &regs->pageflush);
+}
+
+#endif /* !(_SPARC_IOMMU_H) */
diff --git a/arch/sparc/include/asm/iommu_64.h b/arch/sparc/include/asm/iommu_64.h
new file mode 100644
index 00000000000..2b9321ab064
--- /dev/null
+++ b/arch/sparc/include/asm/iommu_64.h
@@ -0,0 +1,65 @@
+/* iommu.h: Definitions for the sun5 IOMMU.
+ *
+ * Copyright (C) 1996, 1999, 2007 David S. Miller (davem@davemloft.net)
+ */
+#ifndef _SPARC64_IOMMU_H
+#define _SPARC64_IOMMU_H
+
+/* The format of an iopte in the page tables. */
+#define IOPTE_VALID 0x8000000000000000UL
+#define IOPTE_64K 0x2000000000000000UL
+#define IOPTE_STBUF 0x1000000000000000UL
+#define IOPTE_INTRA 0x0800000000000000UL
+#define IOPTE_CONTEXT 0x07ff800000000000UL
+#define IOPTE_PAGE 0x00007fffffffe000UL
+#define IOPTE_CACHE 0x0000000000000010UL
+#define IOPTE_WRITE 0x0000000000000002UL
+
+#define IOMMU_NUM_CTXS 4096
+
+struct iommu_arena {
+ unsigned long *map;
+ unsigned int hint;
+ unsigned int limit;
+};
+
+struct iommu {
+ spinlock_t lock;
+ struct iommu_arena arena;
+ void (*flush_all)(struct iommu *);
+ iopte_t *page_table;
+ u32 page_table_map_base;
+ unsigned long iommu_control;
+ unsigned long iommu_tsbbase;
+ unsigned long iommu_flush;
+ unsigned long iommu_flushinv;
+ unsigned long iommu_tags;
+ unsigned long iommu_ctxflush;
+ unsigned long write_complete_reg;
+ unsigned long dummy_page;
+ unsigned long dummy_page_pa;
+ unsigned long ctx_lowest_free;
+ DECLARE_BITMAP(ctx_bitmap, IOMMU_NUM_CTXS);
+ u32 dma_addr_mask;
+};
+
+struct strbuf {
+ int strbuf_enabled;
+ unsigned long strbuf_control;
+ unsigned long strbuf_pflush;
+ unsigned long strbuf_fsync;
+ unsigned long strbuf_err_stat;
+ unsigned long strbuf_tag_diag;
+ unsigned long strbuf_line_diag;
+ unsigned long strbuf_ctxflush;
+ unsigned long strbuf_ctxmatch_base;
+ unsigned long strbuf_flushflag_pa;
+ volatile unsigned long *strbuf_flushflag;
+ volatile unsigned long __flushflag_buf[(64+(64-1)) / sizeof(long)];
+};
+
+int iommu_table_init(struct iommu *iommu, int tsbsize,
+ u32 dma_offset, u32 dma_addr_mask,
+ int numa_node);
+
+#endif /* !(_SPARC64_IOMMU_H) */
diff --git a/arch/sparc/include/asm/irq.h b/arch/sparc/include/asm/irq.h
new file mode 100644
index 00000000000..3b44a6a1407
--- /dev/null
+++ b/arch/sparc/include/asm/irq.h
@@ -0,0 +1,8 @@
+#ifndef ___ASM_SPARC_IRQ_H
+#define ___ASM_SPARC_IRQ_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/irq_64.h>
+#else
+#include <asm/irq_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/irq_32.h b/arch/sparc/include/asm/irq_32.h
new file mode 100644
index 00000000000..eecd3d8442c
--- /dev/null
+++ b/arch/sparc/include/asm/irq_32.h
@@ -0,0 +1,24 @@
+/* irq.h: IRQ registers on the Sparc.
+ *
+ * Copyright (C) 1995, 2007 David S. Miller (davem@davemloft.net)
+ */
+
+#ifndef _SPARC_IRQ_H
+#define _SPARC_IRQ_H
+
+/* Allocated number of logical irq numbers.
+ * sun4d boxes (ss2000e) should be OK with ~32.
+ * Be on the safe side and make room for 64
+ */
+#define NR_IRQS 64
+
+#include <linux/interrupt.h>
+
+#define irq_canonicalize(irq) (irq)
+
+void __init init_IRQ(void);
+void __init sun4d_init_sbi_irq(void);
+
+#define NO_IRQ 0xffffffff
+
+#endif
diff --git a/arch/sparc/include/asm/irq_64.h b/arch/sparc/include/asm/irq_64.h
new file mode 100644
index 00000000000..91d21938130
--- /dev/null
+++ b/arch/sparc/include/asm/irq_64.h
@@ -0,0 +1,101 @@
+/* irq.h: IRQ registers on the 64-bit Sparc.
+ *
+ * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz)
+ */
+
+#ifndef _SPARC64_IRQ_H
+#define _SPARC64_IRQ_H
+
+#include <linux/linkage.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <asm/pil.h>
+#include <asm/ptrace.h>
+
+/* IMAP/ICLR register defines */
+#define IMAP_VALID 0x80000000UL /* IRQ Enabled */
+#define IMAP_TID_UPA 0x7c000000UL /* UPA TargetID */
+#define IMAP_TID_JBUS 0x7c000000UL /* JBUS TargetID */
+#define IMAP_TID_SHIFT 26
+#define IMAP_AID_SAFARI 0x7c000000UL /* Safari AgentID */
+#define IMAP_AID_SHIFT 26
+#define IMAP_NID_SAFARI 0x03e00000UL /* Safari NodeID */
+#define IMAP_NID_SHIFT 21
+#define IMAP_IGN 0x000007c0UL /* IRQ Group Number */
+#define IMAP_INO 0x0000003fUL /* IRQ Number */
+#define IMAP_INR 0x000007ffUL /* Full interrupt number*/
+
+#define ICLR_IDLE 0x00000000UL /* Idle state */
+#define ICLR_TRANSMIT 0x00000001UL /* Transmit state */
+#define ICLR_PENDING 0x00000003UL /* Pending state */
+
+/* The largest number of unique interrupt sources we support.
+ * If this needs to ever be larger than 255, you need to change
+ * the type of ino_bucket->irq as appropriate.
+ *
+ * ino_bucket->irq allocation is made during {sun4v_,}build_irq().
+ */
+#define NR_IRQS 255
+
+void irq_install_pre_handler(int irq,
+ void (*func)(unsigned int, void *, void *),
+ void *arg1, void *arg2);
+#define irq_canonicalize(irq) (irq)
+unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap);
+unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino);
+unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino);
+unsigned int sun4v_build_msi(u32 devhandle, unsigned int *irq_p,
+ unsigned int msi_devino_start,
+ unsigned int msi_devino_end);
+void sun4v_destroy_msi(unsigned int irq);
+unsigned int sun4u_build_msi(u32 portid, unsigned int *irq_p,
+ unsigned int msi_devino_start,
+ unsigned int msi_devino_end,
+ unsigned long imap_base,
+ unsigned long iclr_base);
+void sun4u_destroy_msi(unsigned int irq);
+
+unsigned char irq_alloc(unsigned int dev_handle,
+ unsigned int dev_ino);
+#ifdef CONFIG_PCI_MSI
+void irq_free(unsigned int irq);
+#endif
+
+void __init init_IRQ(void);
+void fixup_irqs(void);
+
+static inline void set_softint(unsigned long bits)
+{
+ __asm__ __volatile__("wr %0, 0x0, %%set_softint"
+ : /* No outputs */
+ : "r" (bits));
+}
+
+static inline void clear_softint(unsigned long bits)
+{
+ __asm__ __volatile__("wr %0, 0x0, %%clear_softint"
+ : /* No outputs */
+ : "r" (bits));
+}
+
+static inline unsigned long get_softint(void)
+{
+ unsigned long retval;
+
+ __asm__ __volatile__("rd %%softint, %0"
+ : "=r" (retval));
+ return retval;
+}
+
+void arch_trigger_all_cpu_backtrace(bool);
+#define arch_trigger_all_cpu_backtrace arch_trigger_all_cpu_backtrace
+
+extern void *hardirq_stack[NR_CPUS];
+extern void *softirq_stack[NR_CPUS];
+#define __ARCH_HAS_DO_SOFTIRQ
+
+#define NO_IRQ 0xffffffff
+
+#endif
diff --git a/arch/sparc/include/asm/irqflags.h b/arch/sparc/include/asm/irqflags.h
new file mode 100644
index 00000000000..1e138632bd3
--- /dev/null
+++ b/arch/sparc/include/asm/irqflags.h
@@ -0,0 +1,8 @@
+#ifndef ___ASM_SPARC_IRQFLAGS_H
+#define ___ASM_SPARC_IRQFLAGS_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/irqflags_64.h>
+#else
+#include <asm/irqflags_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/irqflags_32.h b/arch/sparc/include/asm/irqflags_32.h
new file mode 100644
index 00000000000..71cc284f55c
--- /dev/null
+++ b/arch/sparc/include/asm/irqflags_32.h
@@ -0,0 +1,47 @@
+/*
+ * include/asm/irqflags.h
+ *
+ * IRQ flags handling
+ *
+ * This file gets included from lowlevel asm headers too, to provide
+ * wrapped versions of the local_irq_*() APIs, based on the
+ * arch_local_irq_*() functions from the lowlevel headers.
+ */
+#ifndef _ASM_IRQFLAGS_H
+#define _ASM_IRQFLAGS_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+#include <asm/psr.h>
+
+void arch_local_irq_restore(unsigned long);
+unsigned long arch_local_irq_save(void);
+void arch_local_irq_enable(void);
+
+static inline notrace unsigned long arch_local_save_flags(void)
+{
+ unsigned long flags;
+
+ asm volatile("rd %%psr, %0" : "=r" (flags));
+ return flags;
+}
+
+static inline notrace void arch_local_irq_disable(void)
+{
+ arch_local_irq_save();
+}
+
+static inline notrace bool arch_irqs_disabled_flags(unsigned long flags)
+{
+ return (flags & PSR_PIL) != 0;
+}
+
+static inline notrace bool arch_irqs_disabled(void)
+{
+ return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+#endif /* (__ASSEMBLY__) */
+
+#endif /* !(_ASM_IRQFLAGS_H) */
diff --git a/arch/sparc/include/asm/irqflags_64.h b/arch/sparc/include/asm/irqflags_64.h
new file mode 100644
index 00000000000..23cd27f6beb
--- /dev/null
+++ b/arch/sparc/include/asm/irqflags_64.h
@@ -0,0 +1,97 @@
+/*
+ * include/asm/irqflags.h
+ *
+ * IRQ flags handling
+ *
+ * This file gets included from lowlevel asm headers too, to provide
+ * wrapped versions of the local_irq_*() APIs, based on the
+ * arch_local_irq_*() functions from the lowlevel headers.
+ */
+#ifndef _ASM_IRQFLAGS_H
+#define _ASM_IRQFLAGS_H
+
+#include <asm/pil.h>
+
+#ifndef __ASSEMBLY__
+
+static inline notrace unsigned long arch_local_save_flags(void)
+{
+ unsigned long flags;
+
+ __asm__ __volatile__(
+ "rdpr %%pil, %0"
+ : "=r" (flags)
+ );
+
+ return flags;
+}
+
+static inline notrace void arch_local_irq_restore(unsigned long flags)
+{
+ __asm__ __volatile__(
+ "wrpr %0, %%pil"
+ : /* no output */
+ : "r" (flags)
+ : "memory"
+ );
+}
+
+static inline notrace void arch_local_irq_disable(void)
+{
+ __asm__ __volatile__(
+ "wrpr %0, %%pil"
+ : /* no outputs */
+ : "i" (PIL_NORMAL_MAX)
+ : "memory"
+ );
+}
+
+static inline notrace void arch_local_irq_enable(void)
+{
+ __asm__ __volatile__(
+ "wrpr 0, %%pil"
+ : /* no outputs */
+ : /* no inputs */
+ : "memory"
+ );
+}
+
+static inline notrace int arch_irqs_disabled_flags(unsigned long flags)
+{
+ return (flags > 0);
+}
+
+static inline notrace int arch_irqs_disabled(void)
+{
+ return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+static inline notrace unsigned long arch_local_irq_save(void)
+{
+ unsigned long flags, tmp;
+
+ /* Disable interrupts to PIL_NORMAL_MAX unless we already
+ * are using PIL_NMI, in which case PIL_NMI is retained.
+ *
+ * The only values we ever program into the %pil are 0,
+ * PIL_NORMAL_MAX and PIL_NMI.
+ *
+ * Since PIL_NMI is the largest %pil value and all bits are
+ * set in it (0xf), it doesn't matter what PIL_NORMAL_MAX
+ * actually is.
+ */
+ __asm__ __volatile__(
+ "rdpr %%pil, %0\n\t"
+ "or %0, %2, %1\n\t"
+ "wrpr %1, 0x0, %%pil"
+ : "=r" (flags), "=r" (tmp)
+ : "i" (PIL_NORMAL_MAX)
+ : "memory"
+ );
+
+ return flags;
+}
+
+#endif /* (__ASSEMBLY__) */
+
+#endif /* !(_ASM_IRQFLAGS_H) */
diff --git a/arch/sparc/include/asm/jump_label.h b/arch/sparc/include/asm/jump_label.h
new file mode 100644
index 00000000000..ec2e2e2aba7
--- /dev/null
+++ b/arch/sparc/include/asm/jump_label.h
@@ -0,0 +1,35 @@
+#ifndef _ASM_SPARC_JUMP_LABEL_H
+#define _ASM_SPARC_JUMP_LABEL_H
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+
+#define JUMP_LABEL_NOP_SIZE 4
+
+static __always_inline bool arch_static_branch(struct static_key *key)
+{
+ asm_volatile_goto("1:\n\t"
+ "nop\n\t"
+ "nop\n\t"
+ ".pushsection __jump_table, \"aw\"\n\t"
+ ".align 4\n\t"
+ ".word 1b, %l[l_yes], %c0\n\t"
+ ".popsection \n\t"
+ : : "i" (key) : : l_yes);
+ return false;
+l_yes:
+ return true;
+}
+
+#endif /* __KERNEL__ */
+
+typedef u32 jump_label_t;
+
+struct jump_entry {
+ jump_label_t code;
+ jump_label_t target;
+ jump_label_t key;
+};
+
+#endif
diff --git a/arch/sparc/include/asm/kdebug.h b/arch/sparc/include/asm/kdebug.h
new file mode 100644
index 00000000000..8d12581ca38
--- /dev/null
+++ b/arch/sparc/include/asm/kdebug.h
@@ -0,0 +1,8 @@
+#ifndef ___ASM_SPARC_KDEBUG_H
+#define ___ASM_SPARC_KDEBUG_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/kdebug_64.h>
+#else
+#include <asm/kdebug_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/kdebug_32.h b/arch/sparc/include/asm/kdebug_32.h
new file mode 100644
index 00000000000..1d0b240222e
--- /dev/null
+++ b/arch/sparc/include/asm/kdebug_32.h
@@ -0,0 +1,74 @@
+/*
+ * kdebug.h: Defines and definitions for debugging the Linux kernel
+ * under various kernel debuggers.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+#ifndef _SPARC_KDEBUG_H
+#define _SPARC_KDEBUG_H
+
+#include <asm/openprom.h>
+#include <asm/vaddrs.h>
+
+/* Breakpoints are enter through trap table entry 126. So in sparc assembly
+ * if you want to drop into the debugger you do:
+ *
+ * t DEBUG_BP_TRAP
+ */
+
+#define DEBUG_BP_TRAP 126
+
+#ifndef __ASSEMBLY__
+/* The debug vector is passed in %o1 at boot time. It is a pointer to
+ * a structure in the debuggers address space. Here is its format.
+ */
+
+typedef unsigned int (*debugger_funct)(void);
+
+struct kernel_debug {
+ /* First the entry point into the debugger. You jump here
+ * to give control over to the debugger.
+ */
+ unsigned long kdebug_entry;
+ unsigned long kdebug_trapme; /* Figure out later... */
+ /* The following is the number of pages that the debugger has
+ * taken from to total pool.
+ */
+ unsigned long *kdebug_stolen_pages;
+ /* Ok, after you remap yourself and/or change the trap table
+ * from what you were left with at boot time you have to call
+ * this synchronization function so the debugger can check out
+ * what you have done.
+ */
+ debugger_funct teach_debugger;
+}; /* I think that is it... */
+
+extern struct kernel_debug *linux_dbvec;
+
+/* Use this macro in C-code to enter the debugger. */
+static inline void sp_enter_debugger(void)
+{
+ __asm__ __volatile__("jmpl %0, %%o7\n\t"
+ "nop\n\t" : :
+ "r" (linux_dbvec) : "o7", "memory");
+}
+
+#define SP_ENTER_DEBUGGER do { \
+ if((linux_dbvec!=0) && ((*(short *)linux_dbvec)!=-1)) \
+ sp_enter_debugger(); \
+ } while(0)
+
+enum die_val {
+ DIE_UNUSED,
+ DIE_OOPS,
+};
+
+#endif /* !(__ASSEMBLY__) */
+
+/* Some nice offset defines for assembler code. */
+#define KDEBUG_ENTRY_OFF 0x0
+#define KDEBUG_DUNNO_OFF 0x4
+#define KDEBUG_DUNNO2_OFF 0x8
+#define KDEBUG_TEACH_OFF 0xc
+
+#endif /* !(_SPARC_KDEBUG_H) */
diff --git a/arch/sparc/include/asm/kdebug_64.h b/arch/sparc/include/asm/kdebug_64.h
new file mode 100644
index 00000000000..04465de8f3b
--- /dev/null
+++ b/arch/sparc/include/asm/kdebug_64.h
@@ -0,0 +1,21 @@
+#ifndef _SPARC64_KDEBUG_H
+#define _SPARC64_KDEBUG_H
+
+struct pt_regs;
+
+void bad_trap(struct pt_regs *, long);
+
+/* Grossly misnamed. */
+enum die_val {
+ DIE_OOPS = 1,
+ DIE_DEBUG, /* ta 0x70 */
+ DIE_DEBUG_2, /* ta 0x71 */
+ DIE_DIE,
+ DIE_TRAP,
+ DIE_TRAP_TL1,
+ DIE_CALL,
+ DIE_NMI,
+ DIE_NMIWATCHDOG,
+};
+
+#endif
diff --git a/arch/sparc/include/asm/kgdb.h b/arch/sparc/include/asm/kgdb.h
new file mode 100644
index 00000000000..47366af7a58
--- /dev/null
+++ b/arch/sparc/include/asm/kgdb.h
@@ -0,0 +1,41 @@
+#ifndef _SPARC_KGDB_H
+#define _SPARC_KGDB_H
+
+#ifdef CONFIG_SPARC32
+#define BUFMAX 2048
+#else
+#define BUFMAX 4096
+#endif
+
+enum regnames {
+ GDB_G0, GDB_G1, GDB_G2, GDB_G3, GDB_G4, GDB_G5, GDB_G6, GDB_G7,
+ GDB_O0, GDB_O1, GDB_O2, GDB_O3, GDB_O4, GDB_O5, GDB_SP, GDB_O7,
+ GDB_L0, GDB_L1, GDB_L2, GDB_L3, GDB_L4, GDB_L5, GDB_L6, GDB_L7,
+ GDB_I0, GDB_I1, GDB_I2, GDB_I3, GDB_I4, GDB_I5, GDB_FP, GDB_I7,
+ GDB_F0,
+ GDB_F31 = GDB_F0 + 31,
+#ifdef CONFIG_SPARC32
+ GDB_Y, GDB_PSR, GDB_WIM, GDB_TBR, GDB_PC, GDB_NPC,
+ GDB_FSR, GDB_CSR,
+#else
+ GDB_F32 = GDB_F0 + 32,
+ GDB_F62 = GDB_F32 + 15,
+ GDB_PC, GDB_NPC, GDB_STATE, GDB_FSR, GDB_FPRS, GDB_Y,
+#endif
+};
+
+#ifdef CONFIG_SPARC32
+#define NUMREGBYTES ((GDB_CSR + 1) * 4)
+#else
+#define NUMREGBYTES ((GDB_Y + 1) * 8)
+
+struct pt_regs;
+asmlinkage void kgdb_trap(unsigned long trap_level, struct pt_regs *regs);
+#endif
+
+void arch_kgdb_breakpoint(void);
+
+#define BREAK_INSTR_SIZE 4
+#define CACHE_FLUSH_IS_SAFE 1
+
+#endif /* _SPARC_KGDB_H */
diff --git a/arch/sparc/include/asm/kmap_types.h b/arch/sparc/include/asm/kmap_types.h
new file mode 100644
index 00000000000..aad21745fbb
--- /dev/null
+++ b/arch/sparc/include/asm/kmap_types.h
@@ -0,0 +1,10 @@
+#ifndef _ASM_KMAP_TYPES_H
+#define _ASM_KMAP_TYPES_H
+
+/* Dummy header just to define km_type. None of this
+ * is actually used on sparc. -DaveM
+ */
+
+#include <asm-generic/kmap_types.h>
+
+#endif
diff --git a/arch/sparc/include/asm/kprobes.h b/arch/sparc/include/asm/kprobes.h
new file mode 100644
index 00000000000..a145d798e11
--- /dev/null
+++ b/arch/sparc/include/asm/kprobes.h
@@ -0,0 +1,51 @@
+#ifndef _SPARC64_KPROBES_H
+#define _SPARC64_KPROBES_H
+
+#include <linux/types.h>
+#include <linux/percpu.h>
+
+typedef u32 kprobe_opcode_t;
+
+#define BREAKPOINT_INSTRUCTION 0x91d02070 /* ta 0x70 */
+#define BREAKPOINT_INSTRUCTION_2 0x91d02071 /* ta 0x71 */
+#define MAX_INSN_SIZE 2
+
+#define kretprobe_blacklist_size 0
+
+#define arch_remove_kprobe(p) do {} while (0)
+
+#define flush_insn_slot(p) \
+do { flushi(&(p)->ainsn.insn[0]); \
+ flushi(&(p)->ainsn.insn[1]); \
+} while (0)
+
+void kretprobe_trampoline(void);
+
+/* Architecture specific copy of original instruction*/
+struct arch_specific_insn {
+ /* copy of the original instruction */
+ kprobe_opcode_t insn[MAX_INSN_SIZE];
+};
+
+struct prev_kprobe {
+ struct kprobe *kp;
+ unsigned long status;
+ unsigned long orig_tnpc;
+ unsigned long orig_tstate_pil;
+};
+
+/* per-cpu kprobe control block */
+struct kprobe_ctlblk {
+ unsigned long kprobe_status;
+ unsigned long kprobe_orig_tnpc;
+ unsigned long kprobe_orig_tstate_pil;
+ struct pt_regs jprobe_saved_regs;
+ struct prev_kprobe prev_kprobe;
+};
+
+int kprobe_exceptions_notify(struct notifier_block *self,
+ unsigned long val, void *data);
+int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
+asmlinkage void __kprobes kprobe_trap(unsigned long trap_level,
+ struct pt_regs *regs);
+#endif /* _SPARC64_KPROBES_H */
diff --git a/arch/sparc/include/asm/ldc.h b/arch/sparc/include/asm/ldc.h
new file mode 100644
index 00000000000..c8c67f621f4
--- /dev/null
+++ b/arch/sparc/include/asm/ldc.h
@@ -0,0 +1,138 @@
+#ifndef _SPARC64_LDC_H
+#define _SPARC64_LDC_H
+
+#include <asm/hypervisor.h>
+
+extern int ldom_domaining_enabled;
+void ldom_set_var(const char *var, const char *value);
+void ldom_reboot(const char *boot_command);
+void ldom_power_off(void);
+
+/* The event handler will be evoked when link state changes
+ * or data becomes available on the receive side.
+ *
+ * For non-RAW links, if the LDC_EVENT_RESET event arrives the
+ * driver should reset all of it's internal state and reinvoke
+ * ldc_connect() to try and bring the link up again.
+ *
+ * For RAW links, ldc_connect() is not used. Instead the driver
+ * just waits for the LDC_EVENT_UP event.
+ */
+struct ldc_channel_config {
+ void (*event)(void *arg, int event);
+
+ u32 mtu;
+ unsigned int rx_irq;
+ unsigned int tx_irq;
+ u8 mode;
+#define LDC_MODE_RAW 0x00
+#define LDC_MODE_UNRELIABLE 0x01
+#define LDC_MODE_RESERVED 0x02
+#define LDC_MODE_STREAM 0x03
+
+ u8 debug;
+#define LDC_DEBUG_HS 0x01
+#define LDC_DEBUG_STATE 0x02
+#define LDC_DEBUG_RX 0x04
+#define LDC_DEBUG_TX 0x08
+#define LDC_DEBUG_DATA 0x10
+};
+
+#define LDC_EVENT_RESET 0x01
+#define LDC_EVENT_UP 0x02
+#define LDC_EVENT_DATA_READY 0x04
+
+#define LDC_STATE_INVALID 0x00
+#define LDC_STATE_INIT 0x01
+#define LDC_STATE_BOUND 0x02
+#define LDC_STATE_READY 0x03
+#define LDC_STATE_CONNECTED 0x04
+
+struct ldc_channel;
+
+/* Allocate state for a channel. */
+struct ldc_channel *ldc_alloc(unsigned long id,
+ const struct ldc_channel_config *cfgp,
+ void *event_arg);
+
+/* Shut down and free state for a channel. */
+void ldc_free(struct ldc_channel *lp);
+
+/* Register TX and RX queues of the link with the hypervisor. */
+int ldc_bind(struct ldc_channel *lp, const char *name);
+
+/* For non-RAW protocols we need to complete a handshake before
+ * communication can proceed. ldc_connect() does that, if the
+ * handshake completes successfully, an LDC_EVENT_UP event will
+ * be sent up to the driver.
+ */
+int ldc_connect(struct ldc_channel *lp);
+int ldc_disconnect(struct ldc_channel *lp);
+
+int ldc_state(struct ldc_channel *lp);
+
+/* Read and write operations. Only valid when the link is up. */
+int ldc_write(struct ldc_channel *lp, const void *buf,
+ unsigned int size);
+int ldc_read(struct ldc_channel *lp, void *buf, unsigned int size);
+
+#define LDC_MAP_SHADOW 0x01
+#define LDC_MAP_DIRECT 0x02
+#define LDC_MAP_IO 0x04
+#define LDC_MAP_R 0x08
+#define LDC_MAP_W 0x10
+#define LDC_MAP_X 0x20
+#define LDC_MAP_RW (LDC_MAP_R | LDC_MAP_W)
+#define LDC_MAP_RWX (LDC_MAP_R | LDC_MAP_W | LDC_MAP_X)
+#define LDC_MAP_ALL 0x03f
+
+struct ldc_trans_cookie {
+ u64 cookie_addr;
+ u64 cookie_size;
+};
+
+struct scatterlist;
+int ldc_map_sg(struct ldc_channel *lp,
+ struct scatterlist *sg, int num_sg,
+ struct ldc_trans_cookie *cookies, int ncookies,
+ unsigned int map_perm);
+
+int ldc_map_single(struct ldc_channel *lp,
+ void *buf, unsigned int len,
+ struct ldc_trans_cookie *cookies, int ncookies,
+ unsigned int map_perm);
+
+void ldc_unmap(struct ldc_channel *lp, struct ldc_trans_cookie *cookies,
+ int ncookies);
+
+int ldc_copy(struct ldc_channel *lp, int copy_dir,
+ void *buf, unsigned int len, unsigned long offset,
+ struct ldc_trans_cookie *cookies, int ncookies);
+
+static inline int ldc_get_dring_entry(struct ldc_channel *lp,
+ void *buf, unsigned int len,
+ unsigned long offset,
+ struct ldc_trans_cookie *cookies,
+ int ncookies)
+{
+ return ldc_copy(lp, LDC_COPY_IN, buf, len, offset, cookies, ncookies);
+}
+
+static inline int ldc_put_dring_entry(struct ldc_channel *lp,
+ void *buf, unsigned int len,
+ unsigned long offset,
+ struct ldc_trans_cookie *cookies,
+ int ncookies)
+{
+ return ldc_copy(lp, LDC_COPY_OUT, buf, len, offset, cookies, ncookies);
+}
+
+void *ldc_alloc_exp_dring(struct ldc_channel *lp, unsigned int len,
+ struct ldc_trans_cookie *cookies,
+ int *ncookies, unsigned int map_perm);
+
+void ldc_free_exp_dring(struct ldc_channel *lp, void *buf,
+ unsigned int len,
+ struct ldc_trans_cookie *cookies, int ncookies);
+
+#endif /* _SPARC64_LDC_H */
diff --git a/arch/sparc/include/asm/leon.h b/arch/sparc/include/asm/leon.h
new file mode 100644
index 00000000000..204771cd74a
--- /dev/null
+++ b/arch/sparc/include/asm/leon.h
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2004 Konrad Eisele (eiselekd@web.de,konrad@gaisler.com) Gaisler Research
+ * Copyright (C) 2004 Stefan Holst (mail@s-holst.de) Uni-Stuttgart
+ * Copyright (C) 2009 Daniel Hellstrom (daniel@gaisler.com) Aeroflex Gaisler AB
+ * Copyright (C) 2009 Konrad Eisele (konrad@gaisler.com) Aeroflex Gaisler AB
+ */
+
+#ifndef LEON_H_INCLUDE
+#define LEON_H_INCLUDE
+
+/* mmu register access, ASI_LEON_MMUREGS */
+#define LEON_CNR_CTRL 0x000
+#define LEON_CNR_CTXP 0x100
+#define LEON_CNR_CTX 0x200
+#define LEON_CNR_F 0x300
+#define LEON_CNR_FADDR 0x400
+
+#define LEON_CNR_CTX_NCTX 256 /*number of MMU ctx */
+
+#define LEON_CNR_CTRL_TLBDIS 0x80000000
+
+#define LEON_MMUTLB_ENT_MAX 64
+
+/*
+ * diagnostic access from mmutlb.vhd:
+ * 0: pte address
+ * 4: pte
+ * 8: additional flags
+ */
+#define LEON_DIAGF_LVL 0x3
+#define LEON_DIAGF_WR 0x8
+#define LEON_DIAGF_WR_SHIFT 3
+#define LEON_DIAGF_HIT 0x10
+#define LEON_DIAGF_HIT_SHIFT 4
+#define LEON_DIAGF_CTX 0x1fe0
+#define LEON_DIAGF_CTX_SHIFT 5
+#define LEON_DIAGF_VALID 0x2000
+#define LEON_DIAGF_VALID_SHIFT 13
+
+/* irq masks */
+#define LEON_HARD_INT(x) (1 << (x)) /* irq 0-15 */
+#define LEON_IRQMASK_R 0x0000fffe /* bit 15- 1 of lregs.irqmask */
+#define LEON_IRQPRIO_R 0xfffe0000 /* bit 31-17 of lregs.irqmask */
+
+#define LEON_MCFG2_SRAMDIS 0x00002000
+#define LEON_MCFG2_SDRAMEN 0x00004000
+#define LEON_MCFG2_SRAMBANKSZ 0x00001e00 /* [12-9] */
+#define LEON_MCFG2_SRAMBANKSZ_SHIFT 9
+#define LEON_MCFG2_SDRAMBANKSZ 0x03800000 /* [25-23] */
+#define LEON_MCFG2_SDRAMBANKSZ_SHIFT 23
+
+#define LEON_TCNT0_MASK 0x7fffff
+
+
+#define ASI_LEON3_SYSCTRL 0x02
+#define ASI_LEON3_SYSCTRL_ICFG 0x08
+#define ASI_LEON3_SYSCTRL_DCFG 0x0c
+#define ASI_LEON3_SYSCTRL_CFG_SNOOPING (1 << 27)
+#define ASI_LEON3_SYSCTRL_CFG_SSIZE(c) (1 << ((c >> 20) & 0xf))
+
+#ifndef __ASSEMBLY__
+
+/* do a physical address bypass write, i.e. for 0x80000000 */
+static inline void leon_store_reg(unsigned long paddr, unsigned long value)
+{
+ __asm__ __volatile__("sta %0, [%1] %2\n\t" : : "r"(value), "r"(paddr),
+ "i"(ASI_LEON_BYPASS) : "memory");
+}
+
+/* do a physical address bypass load, i.e. for 0x80000000 */
+static inline unsigned long leon_load_reg(unsigned long paddr)
+{
+ unsigned long retval;
+ __asm__ __volatile__("lda [%1] %2, %0\n\t" :
+ "=r"(retval) : "r"(paddr), "i"(ASI_LEON_BYPASS));
+ return retval;
+}
+
+/* macro access for leon_load_reg() and leon_store_reg() */
+#define LEON3_BYPASS_LOAD_PA(x) (leon_load_reg((unsigned long)(x)))
+#define LEON3_BYPASS_STORE_PA(x, v) (leon_store_reg((unsigned long)(x), (unsigned long)(v)))
+#define LEON_BYPASS_LOAD_PA(x) leon_load_reg((unsigned long)(x))
+#define LEON_BYPASS_STORE_PA(x, v) leon_store_reg((unsigned long)(x), (unsigned long)(v))
+
+void leon_switch_mm(void);
+void leon_init_IRQ(void);
+
+static inline unsigned long sparc_leon3_get_dcachecfg(void)
+{
+ unsigned int retval;
+ __asm__ __volatile__("lda [%1] %2, %0\n\t" :
+ "=r"(retval) :
+ "r"(ASI_LEON3_SYSCTRL_DCFG),
+ "i"(ASI_LEON3_SYSCTRL));
+ return retval;
+}
+
+/* enable snooping */
+static inline void sparc_leon3_enable_snooping(void)
+{
+ __asm__ __volatile__ ("lda [%%g0] 2, %%l1\n\t"
+ "set 0x800000, %%l2\n\t"
+ "or %%l2, %%l1, %%l2\n\t"
+ "sta %%l2, [%%g0] 2\n\t" : : : "l1", "l2");
+};
+
+static inline int sparc_leon3_snooping_enabled(void)
+{
+ u32 cctrl;
+ __asm__ __volatile__("lda [%%g0] 2, %0\n\t" : "=r"(cctrl));
+ return ((cctrl >> 23) & 1) && ((cctrl >> 17) & 1);
+};
+
+static inline void sparc_leon3_disable_cache(void)
+{
+ __asm__ __volatile__ ("lda [%%g0] 2, %%l1\n\t"
+ "set 0x00000f, %%l2\n\t"
+ "andn %%l2, %%l1, %%l2\n\t"
+ "sta %%l2, [%%g0] 2\n\t" : : : "l1", "l2");
+};
+
+static inline unsigned long sparc_leon3_asr17(void)
+{
+ u32 asr17;
+ __asm__ __volatile__ ("rd %%asr17, %0\n\t" : "=r"(asr17));
+ return asr17;
+};
+
+static inline int sparc_leon3_cpuid(void)
+{
+ return sparc_leon3_asr17() >> 28;
+}
+
+#endif /*!__ASSEMBLY__*/
+
+#ifdef CONFIG_SMP
+# define LEON3_IRQ_IPI_DEFAULT 13
+# define LEON3_IRQ_TICKER (leon3_gptimer_irq)
+# define LEON3_IRQ_CROSS_CALL 15
+#endif
+
+#if defined(PAGE_SIZE_LEON_8K)
+#define LEON_PAGE_SIZE_LEON 1
+#elif defined(PAGE_SIZE_LEON_16K)
+#define LEON_PAGE_SIZE_LEON 2)
+#else
+#define LEON_PAGE_SIZE_LEON 0
+#endif
+
+#if LEON_PAGE_SIZE_LEON == 0
+/* [ 8, 6, 6 ] + 12 */
+#define LEON_PGD_SH 24
+#define LEON_PGD_M 0xff
+#define LEON_PMD_SH 18
+#define LEON_PMD_SH_V (LEON_PGD_SH-2)
+#define LEON_PMD_M 0x3f
+#define LEON_PTE_SH 12
+#define LEON_PTE_M 0x3f
+#elif LEON_PAGE_SIZE_LEON == 1
+/* [ 7, 6, 6 ] + 13 */
+#define LEON_PGD_SH 25
+#define LEON_PGD_M 0x7f
+#define LEON_PMD_SH 19
+#define LEON_PMD_SH_V (LEON_PGD_SH-1)
+#define LEON_PMD_M 0x3f
+#define LEON_PTE_SH 13
+#define LEON_PTE_M 0x3f
+#elif LEON_PAGE_SIZE_LEON == 2
+/* [ 6, 6, 6 ] + 14 */
+#define LEON_PGD_SH 26
+#define LEON_PGD_M 0x3f
+#define LEON_PMD_SH 20
+#define LEON_PMD_SH_V (LEON_PGD_SH-0)
+#define LEON_PMD_M 0x3f
+#define LEON_PTE_SH 14
+#define LEON_PTE_M 0x3f
+#elif LEON_PAGE_SIZE_LEON == 3
+/* [ 4, 7, 6 ] + 15 */
+#define LEON_PGD_SH 28
+#define LEON_PGD_M 0x0f
+#define LEON_PMD_SH 21
+#define LEON_PMD_SH_V (LEON_PGD_SH-0)
+#define LEON_PMD_M 0x7f
+#define LEON_PTE_SH 15
+#define LEON_PTE_M 0x3f
+#else
+#error cannot determine LEON_PAGE_SIZE_LEON
+#endif
+
+#define LEON3_XCCR_SETS_MASK 0x07000000UL
+#define LEON3_XCCR_SSIZE_MASK 0x00f00000UL
+
+#define LEON2_CCR_DSETS_MASK 0x03000000UL
+#define LEON2_CFG_SSIZE_MASK 0x00007000UL
+
+#ifndef __ASSEMBLY__
+struct vm_area_struct;
+
+unsigned long leon_swprobe(unsigned long vaddr, unsigned long *paddr);
+void leon_flush_icache_all(void);
+void leon_flush_dcache_all(void);
+void leon_flush_cache_all(void);
+void leon_flush_tlb_all(void);
+extern int leon_flush_during_switch;
+int leon_flush_needed(void);
+void leon_flush_pcache_all(struct vm_area_struct *vma, unsigned long page);
+
+/* struct that hold LEON3 cache configuration registers */
+struct leon3_cacheregs {
+ unsigned long ccr; /* 0x00 - Cache Control Register */
+ unsigned long iccr; /* 0x08 - Instruction Cache Configuration Register */
+ unsigned long dccr; /* 0x0c - Data Cache Configuration Register */
+};
+
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+struct device_node;
+struct task_struct;
+unsigned int leon_build_device_irq(unsigned int real_irq,
+ irq_flow_handler_t flow_handler,
+ const char *name, int do_ack);
+void leon_update_virq_handling(unsigned int virq,
+ irq_flow_handler_t flow_handler,
+ const char *name, int do_ack);
+void leon_init_timers(void);
+void leon_trans_init(struct device_node *dp);
+void leon_node_init(struct device_node *dp, struct device_node ***nextp);
+void init_leon(void);
+void poke_leonsparc(void);
+void leon3_getCacheRegs(struct leon3_cacheregs *regs);
+extern int leon3_ticker_irq;
+
+#ifdef CONFIG_SMP
+int leon_smp_nrcpus(void);
+void leon_clear_profile_irq(int cpu);
+void leon_smp_done(void);
+void leon_boot_cpus(void);
+int leon_boot_one_cpu(int i, struct task_struct *);
+void leon_init_smp(void);
+void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu);
+irqreturn_t leon_percpu_timer_interrupt(int irq, void *unused);
+
+extern unsigned int smpleon_ipi[];
+extern unsigned int linux_trap_ipi15_leon[];
+extern int leon_ipi_irq;
+
+#endif /* CONFIG_SMP */
+
+#endif /* __ASSEMBLY__ */
+
+/* macros used in leon_mm.c */
+#define PFN(x) ((x) >> PAGE_SHIFT)
+#define _pfn_valid(pfn) ((pfn < last_valid_pfn) && (pfn >= PFN(phys_base)))
+#define _SRMMU_PTE_PMASK_LEON 0xffffffff
+
+#endif
diff --git a/arch/sparc/include/asm/leon_amba.h b/arch/sparc/include/asm/leon_amba.h
new file mode 100644
index 00000000000..24ec48c3ff9
--- /dev/null
+++ b/arch/sparc/include/asm/leon_amba.h
@@ -0,0 +1,266 @@
+/*
+*Copyright (C) 2004 Konrad Eisele (eiselekd@web.de,konrad@gaisler.com), Gaisler Research
+*Copyright (C) 2004 Stefan Holst (mail@s-holst.de), Uni-Stuttgart
+*Copyright (C) 2009 Daniel Hellstrom (daniel@gaisler.com),Konrad Eisele (konrad@gaisler.com) Aeroflex Gaisler AB
+*/
+
+#ifndef LEON_AMBA_H_INCLUDE
+#define LEON_AMBA_H_INCLUDE
+
+#ifndef __ASSEMBLY__
+
+struct amba_prom_registers {
+ unsigned int phys_addr; /* The physical address of this register */
+ unsigned int reg_size; /* How many bytes does this register take up? */
+};
+
+#endif
+
+/*
+ * The following defines the bits in the LEON UART Status Registers.
+ */
+
+#define LEON_REG_UART_STATUS_DR 0x00000001 /* Data Ready */
+#define LEON_REG_UART_STATUS_TSE 0x00000002 /* TX Send Register Empty */
+#define LEON_REG_UART_STATUS_THE 0x00000004 /* TX Hold Register Empty */
+#define LEON_REG_UART_STATUS_BR 0x00000008 /* Break Error */
+#define LEON_REG_UART_STATUS_OE 0x00000010 /* RX Overrun Error */
+#define LEON_REG_UART_STATUS_PE 0x00000020 /* RX Parity Error */
+#define LEON_REG_UART_STATUS_FE 0x00000040 /* RX Framing Error */
+#define LEON_REG_UART_STATUS_ERR 0x00000078 /* Error Mask */
+
+/*
+ * The following defines the bits in the LEON UART Ctrl Registers.
+ */
+
+#define LEON_REG_UART_CTRL_RE 0x00000001 /* Receiver enable */
+#define LEON_REG_UART_CTRL_TE 0x00000002 /* Transmitter enable */
+#define LEON_REG_UART_CTRL_RI 0x00000004 /* Receiver interrupt enable */
+#define LEON_REG_UART_CTRL_TI 0x00000008 /* Transmitter irq */
+#define LEON_REG_UART_CTRL_PS 0x00000010 /* Parity select */
+#define LEON_REG_UART_CTRL_PE 0x00000020 /* Parity enable */
+#define LEON_REG_UART_CTRL_FL 0x00000040 /* Flow control enable */
+#define LEON_REG_UART_CTRL_LB 0x00000080 /* Loop Back enable */
+
+#define LEON3_GPTIMER_EN 1
+#define LEON3_GPTIMER_RL 2
+#define LEON3_GPTIMER_LD 4
+#define LEON3_GPTIMER_IRQEN 8
+#define LEON3_GPTIMER_SEPIRQ 8
+#define LEON3_GPTIMER_TIMERS 0x7
+
+#define LEON23_REG_TIMER_CONTROL_EN 0x00000001 /* 1 = enable counting */
+/* 0 = hold scalar and counter */
+#define LEON23_REG_TIMER_CONTROL_RL 0x00000002 /* 1 = reload at 0 */
+ /* 0 = stop at 0 */
+#define LEON23_REG_TIMER_CONTROL_LD 0x00000004 /* 1 = load counter */
+ /* 0 = no function */
+#define LEON23_REG_TIMER_CONTROL_IQ 0x00000008 /* 1 = irq enable */
+ /* 0 = no function */
+
+/*
+ * The following defines the bits in the LEON PS/2 Status Registers.
+ */
+
+#define LEON_REG_PS2_STATUS_DR 0x00000001 /* Data Ready */
+#define LEON_REG_PS2_STATUS_PE 0x00000002 /* Parity error */
+#define LEON_REG_PS2_STATUS_FE 0x00000004 /* Framing error */
+#define LEON_REG_PS2_STATUS_KI 0x00000008 /* Keyboard inhibit */
+#define LEON_REG_PS2_STATUS_RF 0x00000010 /* RX buffer full */
+#define LEON_REG_PS2_STATUS_TF 0x00000020 /* TX buffer full */
+
+/*
+ * The following defines the bits in the LEON PS/2 Ctrl Registers.
+ */
+
+#define LEON_REG_PS2_CTRL_RE 0x00000001 /* Receiver enable */
+#define LEON_REG_PS2_CTRL_TE 0x00000002 /* Transmitter enable */
+#define LEON_REG_PS2_CTRL_RI 0x00000004 /* Keyboard receive irq */
+#define LEON_REG_PS2_CTRL_TI 0x00000008 /* Keyboard transmit irq */
+
+#define LEON3_IRQMPSTATUS_CPUNR 28
+#define LEON3_IRQMPSTATUS_BROADCAST 27
+
+#define GPTIMER_CONFIG_IRQNT(a) (((a) >> 3) & 0x1f)
+#define GPTIMER_CONFIG_ISSEP(a) ((a) & (1 << 8))
+#define GPTIMER_CONFIG_NTIMERS(a) ((a) & (0x7))
+#define LEON3_GPTIMER_CTRL_PENDING 0x10
+#define LEON3_GPTIMER_CONFIG_NRTIMERS(c) ((c)->config & 0x7)
+#define LEON3_GPTIMER_CTRL_ISPENDING(r) (((r)&LEON3_GPTIMER_CTRL_PENDING) ? 1 : 0)
+
+#ifndef __ASSEMBLY__
+
+struct leon3_irqctrl_regs_map {
+ u32 ilevel;
+ u32 ipend;
+ u32 iforce;
+ u32 iclear;
+ u32 mpstatus;
+ u32 mpbroadcast;
+ u32 notused02;
+ u32 notused03;
+ u32 ampctrl;
+ u32 icsel[2];
+ u32 notused13;
+ u32 notused20;
+ u32 notused21;
+ u32 notused22;
+ u32 notused23;
+ u32 mask[16];
+ u32 force[16];
+ /* Extended IRQ registers */
+ u32 intid[16]; /* 0xc0 */
+ u32 unused[(0x1000-0x100)/4];
+};
+
+struct leon3_apbuart_regs_map {
+ u32 data;
+ u32 status;
+ u32 ctrl;
+ u32 scaler;
+};
+
+struct leon3_gptimerelem_regs_map {
+ u32 val;
+ u32 rld;
+ u32 ctrl;
+ u32 unused;
+};
+
+struct leon3_gptimer_regs_map {
+ u32 scalar;
+ u32 scalar_reload;
+ u32 config;
+ u32 unused;
+ struct leon3_gptimerelem_regs_map e[8];
+};
+
+/*
+ * Types and structure used for AMBA Plug & Play bus scanning
+ */
+
+#define AMBA_MAXAPB_DEVS 64
+#define AMBA_MAXAPB_DEVS_PERBUS 16
+
+struct amba_device_table {
+ int devnr; /* number of devices on AHB or APB bus */
+ unsigned int *addr[16]; /* addresses to the devices configuration tables */
+ unsigned int allocbits[1]; /* 0=unallocated, 1=allocated driver */
+};
+
+struct amba_apbslv_device_table {
+ int devnr; /* number of devices on AHB or APB bus */
+ unsigned int *addr[AMBA_MAXAPB_DEVS]; /* addresses to the devices configuration tables */
+ unsigned int apbmst[AMBA_MAXAPB_DEVS]; /* apb master if a entry is a apb slave */
+ unsigned int apbmstidx[AMBA_MAXAPB_DEVS]; /* apb master idx if a entry is a apb slave */
+ unsigned int allocbits[4]; /* 0=unallocated, 1=allocated driver */
+};
+
+struct amba_confarea_type {
+ struct amba_confarea_type *next;/* next bus in chain */
+ struct amba_device_table ahbmst;
+ struct amba_device_table ahbslv;
+ struct amba_apbslv_device_table apbslv;
+ unsigned int apbmst;
+};
+
+/* collect apb slaves */
+struct amba_apb_device {
+ unsigned int start, irq, bus_id;
+ struct amba_confarea_type *bus;
+};
+
+/* collect ahb slaves */
+struct amba_ahb_device {
+ unsigned int start[4], irq, bus_id;
+ struct amba_confarea_type *bus;
+};
+
+struct device_node;
+void _amba_init(struct device_node *dp, struct device_node ***nextp);
+
+extern unsigned long amba_system_id;
+extern struct leon3_irqctrl_regs_map *leon3_irqctrl_regs;
+extern struct leon3_gptimer_regs_map *leon3_gptimer_regs;
+extern struct amba_apb_device leon_percpu_timer_dev[16];
+extern int leondebug_irq_disable;
+extern int leon_debug_irqout;
+extern unsigned long leon3_gptimer_irq;
+extern unsigned int sparc_leon_eirq;
+
+#endif /* __ASSEMBLY__ */
+
+#define LEON3_IO_AREA 0xfff00000
+#define LEON3_CONF_AREA 0xff000
+#define LEON3_AHB_SLAVE_CONF_AREA (1 << 11)
+
+#define LEON3_AHB_CONF_WORDS 8
+#define LEON3_APB_CONF_WORDS 2
+#define LEON3_AHB_MASTERS 16
+#define LEON3_AHB_SLAVES 16
+#define LEON3_APB_SLAVES 16
+#define LEON3_APBUARTS 8
+
+/* Vendor codes */
+#define VENDOR_GAISLER 1
+#define VENDOR_PENDER 2
+#define VENDOR_ESA 4
+#define VENDOR_OPENCORES 8
+
+/* Gaisler Research device id's */
+#define GAISLER_LEON3 0x003
+#define GAISLER_LEON3DSU 0x004
+#define GAISLER_ETHAHB 0x005
+#define GAISLER_APBMST 0x006
+#define GAISLER_AHBUART 0x007
+#define GAISLER_SRCTRL 0x008
+#define GAISLER_SDCTRL 0x009
+#define GAISLER_APBUART 0x00C
+#define GAISLER_IRQMP 0x00D
+#define GAISLER_AHBRAM 0x00E
+#define GAISLER_GPTIMER 0x011
+#define GAISLER_PCITRG 0x012
+#define GAISLER_PCISBRG 0x013
+#define GAISLER_PCIFBRG 0x014
+#define GAISLER_PCITRACE 0x015
+#define GAISLER_PCIDMA 0x016
+#define GAISLER_AHBTRACE 0x017
+#define GAISLER_ETHDSU 0x018
+#define GAISLER_PIOPORT 0x01A
+#define GAISLER_GRGPIO 0x01A
+#define GAISLER_AHBJTAG 0x01c
+#define GAISLER_ETHMAC 0x01D
+#define GAISLER_AHB2AHB 0x020
+#define GAISLER_USBDC 0x021
+#define GAISLER_ATACTRL 0x024
+#define GAISLER_DDRSPA 0x025
+#define GAISLER_USBEHC 0x026
+#define GAISLER_USBUHC 0x027
+#define GAISLER_I2CMST 0x028
+#define GAISLER_SPICTRL 0x02D
+#define GAISLER_DDR2SPA 0x02E
+#define GAISLER_SPIMCTRL 0x045
+#define GAISLER_LEON4 0x048
+#define GAISLER_LEON4DSU 0x049
+#define GAISLER_AHBSTAT 0x052
+#define GAISLER_FTMCTRL 0x054
+#define GAISLER_KBD 0x060
+#define GAISLER_VGA 0x061
+#define GAISLER_SVGA 0x063
+#define GAISLER_GRSYSMON 0x066
+#define GAISLER_GRACECTRL 0x067
+
+#define GAISLER_L2TIME 0xffd /* internal device: leon2 timer */
+#define GAISLER_L2C 0xffe /* internal device: leon2compat */
+#define GAISLER_PLUGPLAY 0xfff /* internal device: plug & play configarea */
+
+/* Chip IDs */
+#define AEROFLEX_UT699 0x0699
+#define LEON4_NEXTREME1 0x0102
+#define GAISLER_GR712RC 0x0712
+
+#define amba_vendor(x) (((x) >> 24) & 0xff)
+
+#define amba_device(x) (((x) >> 12) & 0xfff)
+
+#endif
diff --git a/arch/sparc/include/asm/leon_pci.h b/arch/sparc/include/asm/leon_pci.h
new file mode 100644
index 00000000000..049d067ed8b
--- /dev/null
+++ b/arch/sparc/include/asm/leon_pci.h
@@ -0,0 +1,22 @@
+/*
+ * asm/leon_pci.h
+ *
+ * Copyright (C) 2011 Aeroflex Gaisler AB, Daniel Hellstrom
+ */
+
+#ifndef _ASM_LEON_PCI_H_
+#define _ASM_LEON_PCI_H_
+
+/* PCI related definitions */
+struct leon_pci_info {
+ struct pci_ops *ops;
+ struct resource io_space;
+ struct resource mem_space;
+ struct resource busn;
+ int (*map_irq)(const struct pci_dev *dev, u8 slot, u8 pin);
+};
+
+void leon_pci_init(struct platform_device *ofdev,
+ struct leon_pci_info *info);
+
+#endif /* _ASM_LEON_PCI_H_ */
diff --git a/arch/sparc/include/asm/lsu.h b/arch/sparc/include/asm/lsu.h
new file mode 100644
index 00000000000..7190f8de90a
--- /dev/null
+++ b/arch/sparc/include/asm/lsu.h
@@ -0,0 +1,19 @@
+#ifndef _SPARC64_LSU_H
+#define _SPARC64_LSU_H
+
+#include <linux/const.h>
+
+/* LSU Control Register */
+#define LSU_CONTROL_PM _AC(0x000001fe00000000,UL) /* Phys-watchpoint byte mask*/
+#define LSU_CONTROL_VM _AC(0x00000001fe000000,UL) /* Virt-watchpoint byte mask*/
+#define LSU_CONTROL_PR _AC(0x0000000001000000,UL) /* Phys-rd watchpoint enable*/
+#define LSU_CONTROL_PW _AC(0x0000000000800000,UL) /* Phys-wr watchpoint enable*/
+#define LSU_CONTROL_VR _AC(0x0000000000400000,UL) /* Virt-rd watchpoint enable*/
+#define LSU_CONTROL_VW _AC(0x0000000000200000,UL) /* Virt-wr watchpoint enable*/
+#define LSU_CONTROL_FM _AC(0x00000000000ffff0,UL) /* Parity mask enables. */
+#define LSU_CONTROL_DM _AC(0x0000000000000008,UL) /* Data MMU enable. */
+#define LSU_CONTROL_IM _AC(0x0000000000000004,UL) /* Instruction MMU enable. */
+#define LSU_CONTROL_DC _AC(0x0000000000000002,UL) /* Data cache enable. */
+#define LSU_CONTROL_IC _AC(0x0000000000000001,UL) /* Instruction cache enable.*/
+
+#endif /* !(_SPARC64_LSU_H) */
diff --git a/arch/sparc/include/asm/machines.h b/arch/sparc/include/asm/machines.h
new file mode 100644
index 00000000000..fd6ddb05d1b
--- /dev/null
+++ b/arch/sparc/include/asm/machines.h
@@ -0,0 +1,50 @@
+/*
+ * machines.h: Defines for taking apart the machine type value in the
+ * idprom and determining the kind of machine we are on.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+#ifndef _SPARC_MACHINES_H
+#define _SPARC_MACHINES_H
+
+struct Sun_Machine_Models {
+ char *name;
+ unsigned char id_machtype;
+};
+
+/* The machine type in the idprom area looks like this:
+ *
+ * ---------------
+ * | ARCH | MACH |
+ * ---------------
+ * 7 4 3 0
+ *
+ * The ARCH field determines the architecture line (sun4m, etc).
+ * The MACH field determines the machine make within that architecture.
+ */
+
+#define SM_ARCH_MASK 0xf0
+#define M_LEON 0x30
+#define SM_SUN4M 0x70
+#define SM_SUN4M_OBP 0x80
+
+#define SM_TYP_MASK 0x0f
+
+/* Leon machines */
+#define M_LEON3_SOC 0x02 /* Leon3 SoC */
+
+/* Sun4m machines, these predate the OpenBoot. These values only mean
+ * something if the value in the ARCH field is SM_SUN4M, if it is
+ * SM_SUN4M_OBP then you have the following situation:
+ * 1) You either have a sun4d, a sun4e, or a recently made sun4m.
+ * 2) You have to consult OpenBoot to determine which machine this is.
+ */
+#define SM_4M_SS60 0x01 /* Sun4m SparcSystem 600 */
+#define SM_4M_SS50 0x02 /* Sun4m SparcStation 10 */
+#define SM_4M_SS40 0x03 /* Sun4m SparcStation 5 */
+
+/* Sun4d machines -- N/A */
+/* Sun4e machines -- N/A */
+/* Sun4u machines -- N/A */
+
+#endif /* !(_SPARC_MACHINES_H) */
diff --git a/arch/sparc/include/asm/mbus.h b/arch/sparc/include/asm/mbus.h
new file mode 100644
index 00000000000..14128bcc582
--- /dev/null
+++ b/arch/sparc/include/asm/mbus.h
@@ -0,0 +1,96 @@
+/*
+ * mbus.h: Various defines for MBUS modules.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _SPARC_MBUS_H
+#define _SPARC_MBUS_H
+
+#include <asm/ross.h> /* HyperSparc stuff */
+#include <asm/viking.h> /* Ugh, bug city... */
+
+enum mbus_module {
+ HyperSparc = 0,
+ Swift_ok = 4,
+ Swift_bad_c = 5,
+ Swift_lots_o_bugs = 6,
+ Tsunami = 7,
+ Viking_12 = 8,
+ Viking_2x = 9,
+ Viking_30 = 10,
+ Viking_35 = 11,
+ Viking_new = 12,
+ TurboSparc = 13,
+ SRMMU_INVAL_MOD = 14,
+};
+
+extern enum mbus_module srmmu_modtype;
+extern unsigned int viking_rev, swift_rev, cypress_rev;
+
+/* HW Mbus module bugs we have to deal with */
+#define HWBUG_COPYBACK_BROKEN 0x00000001
+#define HWBUG_ASIFLUSH_BROKEN 0x00000002
+#define HWBUG_VACFLUSH_BITROT 0x00000004
+#define HWBUG_KERN_ACCBROKEN 0x00000008
+#define HWBUG_KERN_CBITBROKEN 0x00000010
+#define HWBUG_MODIFIED_BITROT 0x00000020
+#define HWBUG_PC_BADFAULT_ADDR 0x00000040
+#define HWBUG_SUPERSCALAR_BAD 0x00000080
+#define HWBUG_PACINIT_BITROT 0x00000100
+
+/* First the module type values. To find out which you have, just load
+ * the mmu control register from ASI_M_MMUREG alternate address space and
+ * shift the value right 28 bits.
+ */
+/* IMPL field means the company which produced the chip. */
+#define MBUS_VIKING 0x4 /* bleech, Texas Instruments Module */
+#define MBUS_LSI 0x3 /* LSI Logics */
+#define MBUS_ROSS 0x1 /* Ross is nice */
+#define MBUS_FMI 0x0 /* Fujitsu Microelectronics/Swift */
+
+/* Ross Module versions */
+#define ROSS_604_REV_CDE 0x0 /* revisions c, d, and e */
+#define ROSS_604_REV_F 0x1 /* revision f */
+#define ROSS_605 0xf /* revision a, a.1, and a.2 */
+#define ROSS_605_REV_B 0xe /* revision b */
+
+/* TI Viking Module versions */
+#define VIKING_REV_12 0x1 /* Version 1.2 or SPARCclassic's CPU */
+#define VIKING_REV_2 0x2 /* Version 2.1, 2.2, 2.3, and 2.4 */
+#define VIKING_REV_30 0x3 /* Version 3.0 */
+#define VIKING_REV_35 0x4 /* Version 3.5 */
+
+/* LSI Logics. */
+#define LSI_L64815 0x0
+
+/* Fujitsu */
+#define FMI_AURORA 0x4 /* MB8690x, a Swift module... */
+#define FMI_TURBO 0x5 /* MB86907, a TurboSparc module... */
+
+/* For multiprocessor support we need to be able to obtain the CPU id and
+ * the MBUS Module id.
+ */
+
+/* The CPU ID is encoded in the trap base register, 20 bits to the left of
+ * bit zero, with 2 bits being significant.
+ */
+#define TBR_ID_SHIFT 20
+
+static inline int get_cpuid(void)
+{
+ register int retval;
+ __asm__ __volatile__("rd %%tbr, %0\n\t"
+ "srl %0, %1, %0\n\t" :
+ "=r" (retval) :
+ "i" (TBR_ID_SHIFT));
+ return (retval & 3);
+}
+
+static inline int get_modid(void)
+{
+ return (get_cpuid() | 0x8);
+}
+
+
+#endif /* !(_SPARC_MBUS_H) */
diff --git a/arch/sparc/include/asm/mc146818rtc.h b/arch/sparc/include/asm/mc146818rtc.h
new file mode 100644
index 00000000000..d8e72f37dc4
--- /dev/null
+++ b/arch/sparc/include/asm/mc146818rtc.h
@@ -0,0 +1,13 @@
+#ifndef ___ASM_SPARC_MC146818RTC_H
+#define ___ASM_SPARC_MC146818RTC_H
+
+#include <linux/spinlock.h>
+
+extern spinlock_t rtc_lock;
+
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/mc146818rtc_64.h>
+#else
+#include <asm/mc146818rtc_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/mc146818rtc_32.h b/arch/sparc/include/asm/mc146818rtc_32.h
new file mode 100644
index 00000000000..fa7eac92658
--- /dev/null
+++ b/arch/sparc/include/asm/mc146818rtc_32.h
@@ -0,0 +1,29 @@
+/*
+ * Machine dependent access functions for RTC registers.
+ */
+#ifndef __ASM_SPARC_MC146818RTC_H
+#define __ASM_SPARC_MC146818RTC_H
+
+#include <asm/io.h>
+
+#ifndef RTC_PORT
+#define RTC_PORT(x) (0x70 + (x))
+#define RTC_ALWAYS_BCD 1 /* RTC operates in binary mode */
+#endif
+
+/*
+ * The yet supported machines all access the RTC index register via
+ * an ISA port access but the way to access the date register differs ...
+ */
+#define CMOS_READ(addr) ({ \
+outb_p((addr),RTC_PORT(0)); \
+inb_p(RTC_PORT(1)); \
+})
+#define CMOS_WRITE(val, addr) ({ \
+outb_p((addr),RTC_PORT(0)); \
+outb_p((val),RTC_PORT(1)); \
+})
+
+#define RTC_IRQ 8
+
+#endif /* __ASM_SPARC_MC146818RTC_H */
diff --git a/arch/sparc/include/asm/mc146818rtc_64.h b/arch/sparc/include/asm/mc146818rtc_64.h
new file mode 100644
index 00000000000..7238d174e0e
--- /dev/null
+++ b/arch/sparc/include/asm/mc146818rtc_64.h
@@ -0,0 +1,28 @@
+/*
+ * Machine dependent access functions for RTC registers.
+ */
+#ifndef __ASM_SPARC64_MC146818RTC_H
+#define __ASM_SPARC64_MC146818RTC_H
+
+#include <asm/io.h>
+
+#ifndef RTC_PORT
+extern unsigned long cmos_regs;
+#define RTC_PORT(x) (cmos_regs + (x))
+#define RTC_ALWAYS_BCD 0
+#endif
+
+/*
+ * The yet supported machines all access the RTC index register via
+ * an ISA port access but the way to access the date register differs ...
+ */
+#define CMOS_READ(addr) ({ \
+outb_p((addr),RTC_PORT(0)); \
+inb_p(RTC_PORT(1)); \
+})
+#define CMOS_WRITE(val, addr) ({ \
+outb_p((addr),RTC_PORT(0)); \
+outb_p((val),RTC_PORT(1)); \
+})
+
+#endif /* __ASM_SPARC64_MC146818RTC_H */
diff --git a/arch/sparc/include/asm/mdesc.h b/arch/sparc/include/asm/mdesc.h
new file mode 100644
index 00000000000..aebeb88f70d
--- /dev/null
+++ b/arch/sparc/include/asm/mdesc.h
@@ -0,0 +1,80 @@
+#ifndef _SPARC64_MDESC_H
+#define _SPARC64_MDESC_H
+
+#include <linux/types.h>
+#include <linux/cpumask.h>
+#include <asm/prom.h>
+
+struct mdesc_handle;
+
+/* Machine description operations are to be surrounded by grab and
+ * release calls. The mdesc_handle returned from the grab is
+ * the first argument to all of the operational calls that work
+ * on mdescs.
+ */
+struct mdesc_handle *mdesc_grab(void);
+void mdesc_release(struct mdesc_handle *);
+
+#define MDESC_NODE_NULL (~(u64)0)
+
+u64 mdesc_node_by_name(struct mdesc_handle *handle,
+ u64 from_node, const char *name);
+#define mdesc_for_each_node_by_name(__hdl, __node, __name) \
+ for (__node = mdesc_node_by_name(__hdl, MDESC_NODE_NULL, __name); \
+ (__node) != MDESC_NODE_NULL; \
+ __node = mdesc_node_by_name(__hdl, __node, __name))
+
+/* Access to property values returned from mdesc_get_property() are
+ * only valid inside of a mdesc_grab()/mdesc_release() sequence.
+ * Once mdesc_release() is called, the memory backed up by these
+ * pointers may reference freed up memory.
+ *
+ * Therefore callers must make copies of any property values
+ * they need.
+ *
+ * These same rules apply to mdesc_node_name().
+ */
+const void *mdesc_get_property(struct mdesc_handle *handle,
+ u64 node, const char *name, int *lenp);
+const char *mdesc_node_name(struct mdesc_handle *hp, u64 node);
+
+/* MD arc iteration, the standard sequence is:
+ *
+ * unsigned long arc;
+ * mdesc_for_each_arc(arc, handle, node, MDESC_ARC_TYPE_{FWD,BACK}) {
+ * unsigned long target = mdesc_arc_target(handle, arc);
+ * ...
+ * }
+ */
+
+#define MDESC_ARC_TYPE_FWD "fwd"
+#define MDESC_ARC_TYPE_BACK "back"
+
+u64 mdesc_next_arc(struct mdesc_handle *handle, u64 from,
+ const char *arc_type);
+#define mdesc_for_each_arc(__arc, __hdl, __node, __type) \
+ for (__arc = mdesc_next_arc(__hdl, __node, __type); \
+ (__arc) != MDESC_NODE_NULL; \
+ __arc = mdesc_next_arc(__hdl, __arc, __type))
+
+u64 mdesc_arc_target(struct mdesc_handle *hp, u64 arc);
+
+void mdesc_update(void);
+
+struct mdesc_notifier_client {
+ void (*add)(struct mdesc_handle *handle, u64 node);
+ void (*remove)(struct mdesc_handle *handle, u64 node);
+
+ const char *node_name;
+ struct mdesc_notifier_client *next;
+};
+
+void mdesc_register_notifier(struct mdesc_notifier_client *client);
+
+void mdesc_fill_in_cpu_data(cpumask_t *mask);
+void mdesc_populate_present_mask(cpumask_t *mask);
+void mdesc_get_page_sizes(cpumask_t *mask, unsigned long *pgsz_mask);
+
+void sun4v_mdesc_init(void);
+
+#endif
diff --git a/arch/sparc/include/asm/memctrl.h b/arch/sparc/include/asm/memctrl.h
new file mode 100644
index 00000000000..4065c56af7b
--- /dev/null
+++ b/arch/sparc/include/asm/memctrl.h
@@ -0,0 +1,9 @@
+#ifndef _SPARC_MEMCTRL_H
+#define _SPARC_MEMCTRL_H
+
+typedef int (*dimm_printer_t)(int synd_code, unsigned long paddr, char *buf, int buflen);
+
+int register_dimm_printer(dimm_printer_t func);
+void unregister_dimm_printer(dimm_printer_t func);
+
+#endif /* _SPARC_MEMCTRL_H */
diff --git a/arch/sparc/include/asm/mman.h b/arch/sparc/include/asm/mman.h
new file mode 100644
index 00000000000..59bb5938d85
--- /dev/null
+++ b/arch/sparc/include/asm/mman.h
@@ -0,0 +1,10 @@
+#ifndef __SPARC_MMAN_H__
+#define __SPARC_MMAN_H__
+
+#include <uapi/asm/mman.h>
+
+#ifndef __ASSEMBLY__
+#define arch_mmap_check(addr,len,flags) sparc_mmap_check(addr,len)
+int sparc_mmap_check(unsigned long addr, unsigned long len);
+#endif
+#endif /* __SPARC_MMAN_H__ */
diff --git a/arch/sparc/include/asm/mmu.h b/arch/sparc/include/asm/mmu.h
new file mode 100644
index 00000000000..88fa313887d
--- /dev/null
+++ b/arch/sparc/include/asm/mmu.h
@@ -0,0 +1,8 @@
+#ifndef ___ASM_SPARC_MMU_H
+#define ___ASM_SPARC_MMU_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/mmu_64.h>
+#else
+#include <asm/mmu_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/mmu_32.h b/arch/sparc/include/asm/mmu_32.h
new file mode 100644
index 00000000000..6f056e535cf
--- /dev/null
+++ b/arch/sparc/include/asm/mmu_32.h
@@ -0,0 +1,10 @@
+#ifndef __MMU_H
+#define __MMU_H
+
+/* Default "unsigned long" context */
+typedef unsigned long mm_context_t;
+
+/* mm/srmmu.c */
+extern ctxd_t *srmmu_ctx_table_phys;
+
+#endif
diff --git a/arch/sparc/include/asm/mmu_64.h b/arch/sparc/include/asm/mmu_64.h
new file mode 100644
index 00000000000..70067ce184b
--- /dev/null
+++ b/arch/sparc/include/asm/mmu_64.h
@@ -0,0 +1,109 @@
+#ifndef __MMU_H
+#define __MMU_H
+
+#include <linux/const.h>
+#include <asm/page.h>
+#include <asm/hypervisor.h>
+
+#define CTX_NR_BITS 13
+
+#define TAG_CONTEXT_BITS ((_AC(1,UL) << CTX_NR_BITS) - _AC(1,UL))
+
+/* UltraSPARC-III+ and later have a feature whereby you can
+ * select what page size the various Data-TLB instances in the
+ * chip. In order to gracefully support this, we put the version
+ * field in a spot outside of the areas of the context register
+ * where this parameter is specified.
+ */
+#define CTX_VERSION_SHIFT 22
+#define CTX_VERSION_MASK ((~0UL) << CTX_VERSION_SHIFT)
+
+#define CTX_PGSZ_8KB _AC(0x0,UL)
+#define CTX_PGSZ_64KB _AC(0x1,UL)
+#define CTX_PGSZ_512KB _AC(0x2,UL)
+#define CTX_PGSZ_4MB _AC(0x3,UL)
+#define CTX_PGSZ_BITS _AC(0x7,UL)
+#define CTX_PGSZ0_NUC_SHIFT 61
+#define CTX_PGSZ1_NUC_SHIFT 58
+#define CTX_PGSZ0_SHIFT 16
+#define CTX_PGSZ1_SHIFT 19
+#define CTX_PGSZ_MASK ((CTX_PGSZ_BITS << CTX_PGSZ0_SHIFT) | \
+ (CTX_PGSZ_BITS << CTX_PGSZ1_SHIFT))
+
+#define CTX_PGSZ_BASE CTX_PGSZ_8KB
+#define CTX_PGSZ_HUGE CTX_PGSZ_4MB
+#define CTX_PGSZ_KERN CTX_PGSZ_4MB
+
+/* Thus, when running on UltraSPARC-III+ and later, we use the following
+ * PRIMARY_CONTEXT register values for the kernel context.
+ */
+#define CTX_CHEETAH_PLUS_NUC \
+ ((CTX_PGSZ_KERN << CTX_PGSZ0_NUC_SHIFT) | \
+ (CTX_PGSZ_BASE << CTX_PGSZ1_NUC_SHIFT))
+
+#define CTX_CHEETAH_PLUS_CTX0 \
+ ((CTX_PGSZ_KERN << CTX_PGSZ0_SHIFT) | \
+ (CTX_PGSZ_BASE << CTX_PGSZ1_SHIFT))
+
+/* If you want "the TLB context number" use CTX_NR_MASK. If you
+ * want "the bits I program into the context registers" use
+ * CTX_HW_MASK.
+ */
+#define CTX_NR_MASK TAG_CONTEXT_BITS
+#define CTX_HW_MASK (CTX_NR_MASK | CTX_PGSZ_MASK)
+
+#define CTX_FIRST_VERSION ((_AC(1,UL) << CTX_VERSION_SHIFT) + _AC(1,UL))
+#define CTX_VALID(__ctx) \
+ (!(((__ctx.sparc64_ctx_val) ^ tlb_context_cache) & CTX_VERSION_MASK))
+#define CTX_HWBITS(__ctx) ((__ctx.sparc64_ctx_val) & CTX_HW_MASK)
+#define CTX_NRBITS(__ctx) ((__ctx.sparc64_ctx_val) & CTX_NR_MASK)
+
+#ifndef __ASSEMBLY__
+
+#define TSB_ENTRY_ALIGNMENT 16
+
+struct tsb {
+ unsigned long tag;
+ unsigned long pte;
+} __attribute__((aligned(TSB_ENTRY_ALIGNMENT)));
+
+void __tsb_insert(unsigned long ent, unsigned long tag, unsigned long pte);
+void tsb_flush(unsigned long ent, unsigned long tag);
+void tsb_init(struct tsb *tsb, unsigned long size);
+
+struct tsb_config {
+ struct tsb *tsb;
+ unsigned long tsb_rss_limit;
+ unsigned long tsb_nentries;
+ unsigned long tsb_reg_val;
+ unsigned long tsb_map_vaddr;
+ unsigned long tsb_map_pte;
+};
+
+#define MM_TSB_BASE 0
+
+#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
+#define MM_TSB_HUGE 1
+#define MM_NUM_TSBS 2
+#else
+#define MM_NUM_TSBS 1
+#endif
+
+typedef struct {
+ spinlock_t lock;
+ unsigned long sparc64_ctx_val;
+ unsigned long huge_pte_count;
+ struct tsb_config tsb_block[MM_NUM_TSBS];
+ struct hv_tsb_descr tsb_descr[MM_NUM_TSBS];
+} mm_context_t;
+
+#endif /* !__ASSEMBLY__ */
+
+#define TSB_CONFIG_TSB 0x00
+#define TSB_CONFIG_RSS_LIMIT 0x08
+#define TSB_CONFIG_NENTRIES 0x10
+#define TSB_CONFIG_REG_VAL 0x18
+#define TSB_CONFIG_MAP_VADDR 0x20
+#define TSB_CONFIG_MAP_PTE 0x28
+
+#endif /* __MMU_H */
diff --git a/arch/sparc/include/asm/mmu_context.h b/arch/sparc/include/asm/mmu_context.h
new file mode 100644
index 00000000000..5531346c64f
--- /dev/null
+++ b/arch/sparc/include/asm/mmu_context.h
@@ -0,0 +1,8 @@
+#ifndef ___ASM_SPARC_MMU_CONTEXT_H
+#define ___ASM_SPARC_MMU_CONTEXT_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/mmu_context_64.h>
+#else
+#include <asm/mmu_context_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/mmu_context_32.h b/arch/sparc/include/asm/mmu_context_32.h
new file mode 100644
index 00000000000..2df2a9be8f6
--- /dev/null
+++ b/arch/sparc/include/asm/mmu_context_32.h
@@ -0,0 +1,35 @@
+#ifndef __SPARC_MMU_CONTEXT_H
+#define __SPARC_MMU_CONTEXT_H
+
+#ifndef __ASSEMBLY__
+
+#include <asm-generic/mm_hooks.h>
+
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
+{
+}
+
+/* Initialize a new mmu context. This is invoked when a new
+ * address space instance (unique or shared) is instantiated.
+ */
+int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
+
+/* Destroy a dead context. This occurs when mmput drops the
+ * mm_users count to zero, the mmaps have been released, and
+ * all the page tables have been flushed. Our job is to destroy
+ * any remaining processor-specific state.
+ */
+void destroy_context(struct mm_struct *mm);
+
+/* Switch the current MM context. */
+void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm,
+ struct task_struct *tsk);
+
+#define deactivate_mm(tsk,mm) do { } while (0)
+
+/* Activate a new MM instance for the current task. */
+#define activate_mm(active_mm, mm) switch_mm((active_mm), (mm), NULL)
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* !(__SPARC_MMU_CONTEXT_H) */
diff --git a/arch/sparc/include/asm/mmu_context_64.h b/arch/sparc/include/asm/mmu_context_64.h
new file mode 100644
index 00000000000..b84be675e50
--- /dev/null
+++ b/arch/sparc/include/asm/mmu_context_64.h
@@ -0,0 +1,156 @@
+#ifndef __SPARC64_MMU_CONTEXT_H
+#define __SPARC64_MMU_CONTEXT_H
+
+/* Derived heavily from Linus's Alpha/AXP ASN code... */
+
+#ifndef __ASSEMBLY__
+
+#include <linux/spinlock.h>
+#include <asm/spitfire.h>
+#include <asm-generic/mm_hooks.h>
+
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
+{
+}
+
+extern spinlock_t ctx_alloc_lock;
+extern unsigned long tlb_context_cache;
+extern unsigned long mmu_context_bmap[];
+
+void get_new_mmu_context(struct mm_struct *mm);
+#ifdef CONFIG_SMP
+void smp_new_mmu_context_version(void);
+#else
+#define smp_new_mmu_context_version() do { } while (0)
+#endif
+
+int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
+void destroy_context(struct mm_struct *mm);
+
+void __tsb_context_switch(unsigned long pgd_pa,
+ struct tsb_config *tsb_base,
+ struct tsb_config *tsb_huge,
+ unsigned long tsb_descr_pa);
+
+static inline void tsb_context_switch(struct mm_struct *mm)
+{
+ __tsb_context_switch(__pa(mm->pgd),
+ &mm->context.tsb_block[0],
+#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
+ (mm->context.tsb_block[1].tsb ?
+ &mm->context.tsb_block[1] :
+ NULL)
+#else
+ NULL
+#endif
+ , __pa(&mm->context.tsb_descr[0]));
+}
+
+void tsb_grow(struct mm_struct *mm,
+ unsigned long tsb_index,
+ unsigned long mm_rss);
+#ifdef CONFIG_SMP
+void smp_tsb_sync(struct mm_struct *mm);
+#else
+#define smp_tsb_sync(__mm) do { } while (0)
+#endif
+
+/* Set MMU context in the actual hardware. */
+#define load_secondary_context(__mm) \
+ __asm__ __volatile__( \
+ "\n661: stxa %0, [%1] %2\n" \
+ " .section .sun4v_1insn_patch, \"ax\"\n" \
+ " .word 661b\n" \
+ " stxa %0, [%1] %3\n" \
+ " .previous\n" \
+ " flush %%g6\n" \
+ : /* No outputs */ \
+ : "r" (CTX_HWBITS((__mm)->context)), \
+ "r" (SECONDARY_CONTEXT), "i" (ASI_DMMU), "i" (ASI_MMU))
+
+void __flush_tlb_mm(unsigned long, unsigned long);
+
+/* Switch the current MM context. */
+static inline void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, struct task_struct *tsk)
+{
+ unsigned long ctx_valid, flags;
+ int cpu;
+
+ if (unlikely(mm == &init_mm))
+ return;
+
+ spin_lock_irqsave(&mm->context.lock, flags);
+ ctx_valid = CTX_VALID(mm->context);
+ if (!ctx_valid)
+ get_new_mmu_context(mm);
+
+ /* We have to be extremely careful here or else we will miss
+ * a TSB grow if we switch back and forth between a kernel
+ * thread and an address space which has it's TSB size increased
+ * on another processor.
+ *
+ * It is possible to play some games in order to optimize the
+ * switch, but the safest thing to do is to unconditionally
+ * perform the secondary context load and the TSB context switch.
+ *
+ * For reference the bad case is, for address space "A":
+ *
+ * CPU 0 CPU 1
+ * run address space A
+ * set cpu0's bits in cpu_vm_mask
+ * switch to kernel thread, borrow
+ * address space A via entry_lazy_tlb
+ * run address space A
+ * set cpu1's bit in cpu_vm_mask
+ * flush_tlb_pending()
+ * reset cpu_vm_mask to just cpu1
+ * TSB grow
+ * run address space A
+ * context was valid, so skip
+ * TSB context switch
+ *
+ * At that point cpu0 continues to use a stale TSB, the one from
+ * before the TSB grow performed on cpu1. cpu1 did not cross-call
+ * cpu0 to update it's TSB because at that point the cpu_vm_mask
+ * only had cpu1 set in it.
+ */
+ load_secondary_context(mm);
+ tsb_context_switch(mm);
+
+ /* Any time a processor runs a context on an address space
+ * for the first time, we must flush that context out of the
+ * local TLB.
+ */
+ cpu = smp_processor_id();
+ if (!ctx_valid || !cpumask_test_cpu(cpu, mm_cpumask(mm))) {
+ cpumask_set_cpu(cpu, mm_cpumask(mm));
+ __flush_tlb_mm(CTX_HWBITS(mm->context),
+ SECONDARY_CONTEXT);
+ }
+ spin_unlock_irqrestore(&mm->context.lock, flags);
+}
+
+#define deactivate_mm(tsk,mm) do { } while (0)
+
+/* Activate a new MM instance for the current task. */
+static inline void activate_mm(struct mm_struct *active_mm, struct mm_struct *mm)
+{
+ unsigned long flags;
+ int cpu;
+
+ spin_lock_irqsave(&mm->context.lock, flags);
+ if (!CTX_VALID(mm->context))
+ get_new_mmu_context(mm);
+ cpu = smp_processor_id();
+ if (!cpumask_test_cpu(cpu, mm_cpumask(mm)))
+ cpumask_set_cpu(cpu, mm_cpumask(mm));
+
+ load_secondary_context(mm);
+ __flush_tlb_mm(CTX_HWBITS(mm->context), SECONDARY_CONTEXT);
+ tsb_context_switch(mm);
+ spin_unlock_irqrestore(&mm->context.lock, flags);
+}
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* !(__SPARC64_MMU_CONTEXT_H) */
diff --git a/arch/sparc/include/asm/mmzone.h b/arch/sparc/include/asm/mmzone.h
new file mode 100644
index 00000000000..99d9b9f577b
--- /dev/null
+++ b/arch/sparc/include/asm/mmzone.h
@@ -0,0 +1,17 @@
+#ifndef _SPARC64_MMZONE_H
+#define _SPARC64_MMZONE_H
+
+#ifdef CONFIG_NEED_MULTIPLE_NODES
+
+#include <linux/cpumask.h>
+
+extern struct pglist_data *node_data[];
+
+#define NODE_DATA(nid) (node_data[nid])
+
+extern int numa_cpu_lookup_table[];
+extern cpumask_t numa_cpumask_lookup_table[];
+
+#endif /* CONFIG_NEED_MULTIPLE_NODES */
+
+#endif /* _SPARC64_MMZONE_H */
diff --git a/arch/sparc/include/asm/msi.h b/arch/sparc/include/asm/msi.h
new file mode 100644
index 00000000000..724ca566705
--- /dev/null
+++ b/arch/sparc/include/asm/msi.h
@@ -0,0 +1,31 @@
+/*
+ * msi.h: Defines specific to the MBus - Sbus - Interface.
+ *
+ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
+ */
+
+#ifndef _SPARC_MSI_H
+#define _SPARC_MSI_H
+
+/*
+ * Locations of MSI Registers.
+ */
+#define MSI_MBUS_ARBEN 0xe0001008 /* MBus Arbiter Enable register */
+
+/*
+ * Useful bits in the MSI Registers.
+ */
+#define MSI_ASYNC_MODE 0x80000000 /* Operate the MSI asynchronously */
+
+
+static inline void msi_set_sync(void)
+{
+ __asm__ __volatile__ ("lda [%0] %1, %%g3\n\t"
+ "andn %%g3, %2, %%g3\n\t"
+ "sta %%g3, [%0] %1\n\t" : :
+ "r" (MSI_MBUS_ARBEN),
+ "i" (ASI_M_CTL), "r" (MSI_ASYNC_MODE) : "g3");
+}
+
+#endif /* !(_SPARC_MSI_H) */
diff --git a/arch/sparc/include/asm/mxcc.h b/arch/sparc/include/asm/mxcc.h
new file mode 100644
index 00000000000..c0517bd05bd
--- /dev/null
+++ b/arch/sparc/include/asm/mxcc.h
@@ -0,0 +1,137 @@
+/*
+ * mxcc.h: Definitions of the Viking MXCC registers
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _SPARC_MXCC_H
+#define _SPARC_MXCC_H
+
+/* These registers are accessed through ASI 0x2. */
+#define MXCC_DATSTREAM 0x1C00000 /* Data stream register */
+#define MXCC_SRCSTREAM 0x1C00100 /* Source stream register */
+#define MXCC_DESSTREAM 0x1C00200 /* Destination stream register */
+#define MXCC_RMCOUNT 0x1C00300 /* Count of references and misses */
+#define MXCC_STEST 0x1C00804 /* Internal self-test */
+#define MXCC_CREG 0x1C00A04 /* Control register */
+#define MXCC_SREG 0x1C00B00 /* Status register */
+#define MXCC_RREG 0x1C00C04 /* Reset register */
+#define MXCC_EREG 0x1C00E00 /* Error code register */
+#define MXCC_PREG 0x1C00F04 /* Address port register */
+
+/* Some MXCC constants. */
+#define MXCC_STREAM_SIZE 0x20 /* Size in bytes of one stream r/w */
+
+/* The MXCC Control Register:
+ *
+ * ----------------------------------------------------------------------
+ * | | RRC | RSV |PRE|MCE|PARE|ECE|RSV|
+ * ----------------------------------------------------------------------
+ * 31 10 9 8-6 5 4 3 2 1-0
+ *
+ * RRC: Controls what you read from MXCC_RMCOUNT reg.
+ * 0=Misses 1=References
+ * PRE: Prefetch enable
+ * MCE: Multiple Command Enable
+ * PARE: Parity enable
+ * ECE: External cache enable
+ */
+
+#define MXCC_CTL_RRC 0x00000200
+#define MXCC_CTL_PRE 0x00000020
+#define MXCC_CTL_MCE 0x00000010
+#define MXCC_CTL_PARE 0x00000008
+#define MXCC_CTL_ECE 0x00000004
+
+/* The MXCC Error Register:
+ *
+ * --------------------------------------------------------
+ * |ME| RSV|CE|PEW|PEE|ASE|EIV| MOPC|ECODE|PRIV|RSV|HPADDR|
+ * --------------------------------------------------------
+ * 31 30 29 28 27 26 25 24-15 14-7 6 5-3 2-0
+ *
+ * ME: Multiple Errors have occurred
+ * CE: Cache consistency Error
+ * PEW: Parity Error during a Write operation
+ * PEE: Parity Error involving the External cache
+ * ASE: ASynchronous Error
+ * EIV: This register is toast
+ * MOPC: MXCC Operation Code for instance causing error
+ * ECODE: The Error CODE
+ * PRIV: A privileged mode error? 0=no 1=yes
+ * HPADDR: High PhysicalADDRess bits (35-32)
+ */
+
+#define MXCC_ERR_ME 0x80000000
+#define MXCC_ERR_CE 0x20000000
+#define MXCC_ERR_PEW 0x10000000
+#define MXCC_ERR_PEE 0x08000000
+#define MXCC_ERR_ASE 0x04000000
+#define MXCC_ERR_EIV 0x02000000
+#define MXCC_ERR_MOPC 0x01FF8000
+#define MXCC_ERR_ECODE 0x00007F80
+#define MXCC_ERR_PRIV 0x00000040
+#define MXCC_ERR_HPADDR 0x0000000f
+
+/* The MXCC Port register:
+ *
+ * -----------------------------------------------------
+ * | | MID | |
+ * -----------------------------------------------------
+ * 31 21 20-18 17 0
+ *
+ * MID: The moduleID of the cpu your read this from.
+ */
+
+#ifndef __ASSEMBLY__
+
+static inline void mxcc_set_stream_src(unsigned long *paddr)
+{
+ unsigned long data0 = paddr[0];
+ unsigned long data1 = paddr[1];
+
+ __asm__ __volatile__ ("or %%g0, %0, %%g2\n\t"
+ "or %%g0, %1, %%g3\n\t"
+ "stda %%g2, [%2] %3\n\t" : :
+ "r" (data0), "r" (data1),
+ "r" (MXCC_SRCSTREAM),
+ "i" (ASI_M_MXCC) : "g2", "g3");
+}
+
+static inline void mxcc_set_stream_dst(unsigned long *paddr)
+{
+ unsigned long data0 = paddr[0];
+ unsigned long data1 = paddr[1];
+
+ __asm__ __volatile__ ("or %%g0, %0, %%g2\n\t"
+ "or %%g0, %1, %%g3\n\t"
+ "stda %%g2, [%2] %3\n\t" : :
+ "r" (data0), "r" (data1),
+ "r" (MXCC_DESSTREAM),
+ "i" (ASI_M_MXCC) : "g2", "g3");
+}
+
+static inline unsigned long mxcc_get_creg(void)
+{
+ unsigned long mxcc_control;
+
+ __asm__ __volatile__("set 0xffffffff, %%g2\n\t"
+ "set 0xffffffff, %%g3\n\t"
+ "stda %%g2, [%1] %2\n\t"
+ "lda [%3] %2, %0\n\t" :
+ "=r" (mxcc_control) :
+ "r" (MXCC_EREG), "i" (ASI_M_MXCC),
+ "r" (MXCC_CREG) : "g2", "g3");
+ return mxcc_control;
+}
+
+static inline void mxcc_set_creg(unsigned long mxcc_control)
+{
+ __asm__ __volatile__("sta %0, [%1] %2\n\t" : :
+ "r" (mxcc_control), "r" (MXCC_CREG),
+ "i" (ASI_M_MXCC));
+}
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* !(_SPARC_MXCC_H) */
diff --git a/arch/sparc/include/asm/nmi.h b/arch/sparc/include/asm/nmi.h
new file mode 100644
index 00000000000..26ad2b2607c
--- /dev/null
+++ b/arch/sparc/include/asm/nmi.h
@@ -0,0 +1,13 @@
+#ifndef __NMI_H
+#define __NMI_H
+
+int __init nmi_init(void);
+void perfctr_irq(int irq, struct pt_regs *regs);
+void nmi_adjust_hz(unsigned int new_hz);
+
+extern atomic_t nmi_active;
+
+void start_nmi_watchdog(void *unused);
+void stop_nmi_watchdog(void *unused);
+
+#endif /* __NMI_H */
diff --git a/arch/sparc/include/asm/ns87303.h b/arch/sparc/include/asm/ns87303.h
new file mode 100644
index 00000000000..6b947ee0f6a
--- /dev/null
+++ b/arch/sparc/include/asm/ns87303.h
@@ -0,0 +1,117 @@
+/* ns87303.h: Configuration Register Description for the
+ * National Semiconductor PC87303 (SuperIO).
+ *
+ * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
+ */
+
+#ifndef _SPARC_NS87303_H
+#define _SPARC_NS87303_H 1
+
+/*
+ * Control Register Index Values
+ */
+#define FER 0x00
+#define FAR 0x01
+#define PTR 0x02
+#define FCR 0x03
+#define PCR 0x04
+#define KRR 0x05
+#define PMC 0x06
+#define TUP 0x07
+#define SID 0x08
+#define ASC 0x09
+#define CS0CF0 0x0a
+#define CS0CF1 0x0b
+#define CS1CF0 0x0c
+#define CS1CF1 0x0d
+
+/* Function Enable Register (FER) bits */
+#define FER_EDM 0x10 /* Encoded Drive and Motor pin information */
+
+/* Function Address Register (FAR) bits */
+#define FAR_LPT_MASK 0x03
+#define FAR_LPTB 0x00
+#define FAR_LPTA 0x01
+#define FAR_LPTC 0x02
+
+/* Power and Test Register (PTR) bits */
+#define PTR_LPTB_IRQ7 0x08
+#define PTR_LEVEL_IRQ 0x80 /* When not ECP/EPP: Use level IRQ */
+#define PTR_LPT_REG_DIR 0x80 /* When ECP/EPP: LPT CTR controls direction */
+ /* of the parallel port */
+
+/* Function Control Register (FCR) bits */
+#define FCR_LDE 0x10 /* Logical Drive Exchange */
+#define FCR_ZWS_ENA 0x20 /* Enable short host read/write in ECP/EPP */
+
+/* Printer Control Register (PCR) bits */
+#define PCR_EPP_ENABLE 0x01
+#define PCR_EPP_IEEE 0x02 /* Enable EPP Version 1.9 (IEEE 1284) */
+#define PCR_ECP_ENABLE 0x04
+#define PCR_ECP_CLK_ENA 0x08 /* If 0 ECP Clock is stopped on Power down */
+#define PCR_IRQ_POLAR 0x20 /* If 0 IRQ is level high or negative pulse, */
+ /* if 1 polarity is inverted */
+#define PCR_IRQ_ODRAIN 0x40 /* If 1, IRQ is open drain */
+
+/* Tape UARTs and Parallel Port Config Register (TUP) bits */
+#define TUP_EPP_TIMO 0x02 /* Enable EPP timeout IRQ */
+
+/* Advanced SuperIO Config Register (ASC) bits */
+#define ASC_LPT_IRQ7 0x01 /* Always use IRQ7 for LPT */
+#define ASC_DRV2_SEL 0x02 /* Logical Drive Exchange controlled by TDR */
+
+#define FER_RESERVED 0x00
+#define FAR_RESERVED 0x00
+#define PTR_RESERVED 0x73
+#define FCR_RESERVED 0xc4
+#define PCR_RESERVED 0x10
+#define KRR_RESERVED 0x00
+#define PMC_RESERVED 0x98
+#define TUP_RESERVED 0xfb
+#define SIP_RESERVED 0x00
+#define ASC_RESERVED 0x18
+#define CS0CF0_RESERVED 0x00
+#define CS0CF1_RESERVED 0x08
+#define CS1CF0_RESERVED 0x00
+#define CS1CF1_RESERVED 0x08
+
+#ifdef __KERNEL__
+
+#include <linux/spinlock.h>
+
+#include <asm/io.h>
+
+extern spinlock_t ns87303_lock;
+
+static inline int ns87303_modify(unsigned long port, unsigned int index,
+ unsigned char clr, unsigned char set)
+{
+ static unsigned char reserved[] = {
+ FER_RESERVED, FAR_RESERVED, PTR_RESERVED, FCR_RESERVED,
+ PCR_RESERVED, KRR_RESERVED, PMC_RESERVED, TUP_RESERVED,
+ SIP_RESERVED, ASC_RESERVED, CS0CF0_RESERVED, CS0CF1_RESERVED,
+ CS1CF0_RESERVED, CS1CF1_RESERVED
+ };
+ unsigned long flags;
+ unsigned char value;
+
+ if (index > 0x0d)
+ return -EINVAL;
+
+ spin_lock_irqsave(&ns87303_lock, flags);
+
+ outb(index, port);
+ value = inb(port + 1);
+ value &= ~(reserved[index] | clr);
+ value |= set;
+ outb(value, port + 1);
+ outb(value, port + 1);
+
+ spin_unlock_irqrestore(&ns87303_lock, flags);
+
+ return 0;
+}
+
+#endif /* __KERNEL__ */
+
+#endif /* !(_SPARC_NS87303_H) */
diff --git a/arch/sparc/include/asm/obio.h b/arch/sparc/include/asm/obio.h
new file mode 100644
index 00000000000..910c1d9af1f
--- /dev/null
+++ b/arch/sparc/include/asm/obio.h
@@ -0,0 +1,225 @@
+/*
+ * obio.h: Some useful locations in 0xFXXXXXXXX PA obio space on sun4d.
+ *
+ * Copyright (C) 1997 Jakub Jelinek <jj@sunsite.mff.cuni.cz>
+ */
+
+#ifndef _SPARC_OBIO_H
+#define _SPARC_OBIO_H
+
+#include <asm/asi.h>
+
+/* This weird monster likes to use the very upper parts of
+ 36bit PA for these things :) */
+
+/* CSR space (for each XDBUS)
+ * ------------------------------------------------------------------------
+ * | 0xFE | DEVID | | XDBUS ID | |
+ * ------------------------------------------------------------------------
+ * 35 28 27 20 19 10 9 8 7 0
+ */
+
+#define CSR_BASE_ADDR 0xe0000000
+#define CSR_CPU_SHIFT (32 - 4 - 5)
+#define CSR_XDBUS_SHIFT 8
+
+#define CSR_BASE(cpu) (((CSR_BASE_ADDR >> CSR_CPU_SHIFT) + cpu) << CSR_CPU_SHIFT)
+
+/* ECSR space (not for each XDBUS)
+ * ------------------------------------------------------------------------
+ * | 0xF | DEVID[7:1] | |
+ * ------------------------------------------------------------------------
+ * 35 32 31 25 24 0
+ */
+
+#define ECSR_BASE_ADDR 0x00000000
+#define ECSR_CPU_SHIFT (32 - 5)
+#define ECSR_DEV_SHIFT (32 - 8)
+
+#define ECSR_BASE(cpu) ((cpu) << ECSR_CPU_SHIFT)
+#define ECSR_DEV_BASE(devid) ((devid) << ECSR_DEV_SHIFT)
+
+/* Bus Watcher */
+#define BW_LOCAL_BASE 0xfff00000
+
+#define BW_CID 0x00000000
+#define BW_DBUS_CTRL 0x00000008
+#define BW_DBUS_DATA 0x00000010
+#define BW_CTRL 0x00001000
+#define BW_INTR_TABLE 0x00001040
+#define BW_INTR_TABLE_CLEAR 0x00001080
+#define BW_PRESCALER 0x000010c0
+#define BW_PTIMER_LIMIT 0x00002000
+#define BW_PTIMER_COUNTER2 0x00002004
+#define BW_PTIMER_NDLIMIT 0x00002008
+#define BW_PTIMER_CTRL 0x0000200c
+#define BW_PTIMER_COUNTER 0x00002010
+#define BW_TIMER_LIMIT 0x00003000
+#define BW_TIMER_COUNTER2 0x00003004
+#define BW_TIMER_NDLIMIT 0x00003008
+#define BW_TIMER_CTRL 0x0000300c
+#define BW_TIMER_COUNTER 0x00003010
+
+/* BW Control */
+#define BW_CTRL_USER_TIMER 0x00000004 /* Is User Timer Free run enabled */
+
+/* Boot Bus */
+#define BB_LOCAL_BASE 0xf0000000
+
+#define BB_STAT1 0x00100000
+#define BB_STAT2 0x00120000
+#define BB_STAT3 0x00140000
+#define BB_LEDS 0x002e0000
+
+/* Bits in BB_STAT2 */
+#define BB_STAT2_AC_INTR 0x04 /* Aiee! 5ms and power is gone... */
+#define BB_STAT2_TMP_INTR 0x10 /* My Penguins are burning. Are you able to smell it? */
+#define BB_STAT2_FAN_INTR 0x20 /* My fan refuses to work */
+#define BB_STAT2_PWR_INTR 0x40 /* On SC2000, one of the two ACs died. Ok, we go on... */
+#define BB_STAT2_MASK (BB_STAT2_AC_INTR|BB_STAT2_TMP_INTR|BB_STAT2_FAN_INTR|BB_STAT2_PWR_INTR)
+
+/* Cache Controller */
+#define CC_BASE 0x1F00000
+#define CC_DATSTREAM 0x1F00000 /* Data stream register */
+#define CC_DATSIZE 0x1F0003F /* Size */
+#define CC_SRCSTREAM 0x1F00100 /* Source stream register */
+#define CC_DESSTREAM 0x1F00200 /* Destination stream register */
+#define CC_RMCOUNT 0x1F00300 /* Count of references and misses */
+#define CC_IPEN 0x1F00406 /* Pending Interrupts */
+#define CC_IMSK 0x1F00506 /* Interrupt Mask */
+#define CC_ICLR 0x1F00606 /* Clear pending Interrupts */
+#define CC_IGEN 0x1F00704 /* Generate Interrupt register */
+#define CC_STEST 0x1F00804 /* Internal self-test */
+#define CC_CREG 0x1F00A04 /* Control register */
+#define CC_SREG 0x1F00B00 /* Status register */
+#define CC_RREG 0x1F00C04 /* Reset register */
+#define CC_EREG 0x1F00E00 /* Error code register */
+#define CC_CID 0x1F00F04 /* Component ID */
+
+#ifndef __ASSEMBLY__
+
+static inline int bw_get_intr_mask(int sbus_level)
+{
+ int mask;
+
+ __asm__ __volatile__ ("lduha [%1] %2, %0" :
+ "=r" (mask) :
+ "r" (BW_LOCAL_BASE + BW_INTR_TABLE + (sbus_level << 3)),
+ "i" (ASI_M_CTL));
+ return mask;
+}
+
+static inline void bw_clear_intr_mask(int sbus_level, int mask)
+{
+ __asm__ __volatile__ ("stha %0, [%1] %2" : :
+ "r" (mask),
+ "r" (BW_LOCAL_BASE + BW_INTR_TABLE_CLEAR + (sbus_level << 3)),
+ "i" (ASI_M_CTL));
+}
+
+static inline unsigned bw_get_prof_limit(int cpu)
+{
+ unsigned limit;
+
+ __asm__ __volatile__ ("lda [%1] %2, %0" :
+ "=r" (limit) :
+ "r" (CSR_BASE(cpu) + BW_PTIMER_LIMIT),
+ "i" (ASI_M_CTL));
+ return limit;
+}
+
+static inline void bw_set_prof_limit(int cpu, unsigned limit)
+{
+ __asm__ __volatile__ ("sta %0, [%1] %2" : :
+ "r" (limit),
+ "r" (CSR_BASE(cpu) + BW_PTIMER_LIMIT),
+ "i" (ASI_M_CTL));
+}
+
+static inline unsigned bw_get_ctrl(int cpu)
+{
+ unsigned ctrl;
+
+ __asm__ __volatile__ ("lda [%1] %2, %0" :
+ "=r" (ctrl) :
+ "r" (CSR_BASE(cpu) + BW_CTRL),
+ "i" (ASI_M_CTL));
+ return ctrl;
+}
+
+static inline void bw_set_ctrl(int cpu, unsigned ctrl)
+{
+ __asm__ __volatile__ ("sta %0, [%1] %2" : :
+ "r" (ctrl),
+ "r" (CSR_BASE(cpu) + BW_CTRL),
+ "i" (ASI_M_CTL));
+}
+
+static inline unsigned cc_get_ipen(void)
+{
+ unsigned pending;
+
+ __asm__ __volatile__ ("lduha [%1] %2, %0" :
+ "=r" (pending) :
+ "r" (CC_IPEN),
+ "i" (ASI_M_MXCC));
+ return pending;
+}
+
+static inline void cc_set_iclr(unsigned clear)
+{
+ __asm__ __volatile__ ("stha %0, [%1] %2" : :
+ "r" (clear),
+ "r" (CC_ICLR),
+ "i" (ASI_M_MXCC));
+}
+
+static inline unsigned cc_get_imsk(void)
+{
+ unsigned mask;
+
+ __asm__ __volatile__ ("lduha [%1] %2, %0" :
+ "=r" (mask) :
+ "r" (CC_IMSK),
+ "i" (ASI_M_MXCC));
+ return mask;
+}
+
+static inline void cc_set_imsk(unsigned mask)
+{
+ __asm__ __volatile__ ("stha %0, [%1] %2" : :
+ "r" (mask),
+ "r" (CC_IMSK),
+ "i" (ASI_M_MXCC));
+}
+
+static inline unsigned cc_get_imsk_other(int cpuid)
+{
+ unsigned mask;
+
+ __asm__ __volatile__ ("lduha [%1] %2, %0" :
+ "=r" (mask) :
+ "r" (ECSR_BASE(cpuid) | CC_IMSK),
+ "i" (ASI_M_CTL));
+ return mask;
+}
+
+static inline void cc_set_imsk_other(int cpuid, unsigned mask)
+{
+ __asm__ __volatile__ ("stha %0, [%1] %2" : :
+ "r" (mask),
+ "r" (ECSR_BASE(cpuid) | CC_IMSK),
+ "i" (ASI_M_CTL));
+}
+
+static inline void cc_set_igen(unsigned gen)
+{
+ __asm__ __volatile__ ("sta %0, [%1] %2" : :
+ "r" (gen),
+ "r" (CC_IGEN),
+ "i" (ASI_M_MXCC));
+}
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* !(_SPARC_OBIO_H) */
diff --git a/arch/sparc/include/asm/openprom.h b/arch/sparc/include/asm/openprom.h
new file mode 100644
index 00000000000..47eaafad15c
--- /dev/null
+++ b/arch/sparc/include/asm/openprom.h
@@ -0,0 +1,279 @@
+#ifndef __SPARC_OPENPROM_H
+#define __SPARC_OPENPROM_H
+
+/* openprom.h: Prom structures and defines for access to the OPENBOOT
+ * prom routines and data areas.
+ *
+ * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+/* Empirical constants... */
+#define LINUX_OPPROM_MAGIC 0x10010407
+
+#ifndef __ASSEMBLY__
+#include <linux/of.h>
+
+/* V0 prom device operations. */
+struct linux_dev_v0_funcs {
+ int (*v0_devopen)(char *device_str);
+ int (*v0_devclose)(int dev_desc);
+ int (*v0_rdblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
+ int (*v0_wrblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
+ int (*v0_wrnetdev)(int dev_desc, int num_bytes, char *buf);
+ int (*v0_rdnetdev)(int dev_desc, int num_bytes, char *buf);
+ int (*v0_rdchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
+ int (*v0_wrchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
+ int (*v0_seekdev)(int dev_desc, long logical_offst, int from);
+};
+
+/* V2 and later prom device operations. */
+struct linux_dev_v2_funcs {
+ phandle (*v2_inst2pkg)(int d); /* Convert ihandle to phandle */
+ char * (*v2_dumb_mem_alloc)(char *va, unsigned sz);
+ void (*v2_dumb_mem_free)(char *va, unsigned sz);
+
+ /* To map devices into virtual I/O space. */
+ char * (*v2_dumb_mmap)(char *virta, int which_io, unsigned paddr, unsigned sz);
+ void (*v2_dumb_munmap)(char *virta, unsigned size);
+
+ int (*v2_dev_open)(char *devpath);
+ void (*v2_dev_close)(int d);
+ int (*v2_dev_read)(int d, char *buf, int nbytes);
+ int (*v2_dev_write)(int d, const char *buf, int nbytes);
+ int (*v2_dev_seek)(int d, int hi, int lo);
+
+ /* Never issued (multistage load support) */
+ void (*v2_wheee2)(void);
+ void (*v2_wheee3)(void);
+};
+
+struct linux_mlist_v0 {
+ struct linux_mlist_v0 *theres_more;
+ unsigned int start_adr;
+ unsigned num_bytes;
+};
+
+struct linux_mem_v0 {
+ struct linux_mlist_v0 **v0_totphys;
+ struct linux_mlist_v0 **v0_prommap;
+ struct linux_mlist_v0 **v0_available; /* What we can use */
+};
+
+/* Arguments sent to the kernel from the boot prompt. */
+struct linux_arguments_v0 {
+ char *argv[8];
+ char args[100];
+ char boot_dev[2];
+ int boot_dev_ctrl;
+ int boot_dev_unit;
+ int dev_partition;
+ char *kernel_file_name;
+ void *aieee1; /* XXX */
+};
+
+/* V2 and up boot things. */
+struct linux_bootargs_v2 {
+ char **bootpath;
+ char **bootargs;
+ int *fd_stdin;
+ int *fd_stdout;
+};
+
+/* The top level PROM vector. */
+struct linux_romvec {
+ /* Version numbers. */
+ unsigned int pv_magic_cookie;
+ unsigned int pv_romvers;
+ unsigned int pv_plugin_revision;
+ unsigned int pv_printrev;
+
+ /* Version 0 memory descriptors. */
+ struct linux_mem_v0 pv_v0mem;
+
+ /* Node operations. */
+ struct linux_nodeops *pv_nodeops;
+
+ char **pv_bootstr;
+ struct linux_dev_v0_funcs pv_v0devops;
+
+ char *pv_stdin;
+ char *pv_stdout;
+#define PROMDEV_KBD 0 /* input from keyboard */
+#define PROMDEV_SCREEN 0 /* output to screen */
+#define PROMDEV_TTYA 1 /* in/out to ttya */
+#define PROMDEV_TTYB 2 /* in/out to ttyb */
+
+ /* Blocking getchar/putchar. NOT REENTRANT! (grr) */
+ int (*pv_getchar)(void);
+ void (*pv_putchar)(int ch);
+
+ /* Non-blocking variants. */
+ int (*pv_nbgetchar)(void);
+ int (*pv_nbputchar)(int ch);
+
+ void (*pv_putstr)(char *str, int len);
+
+ /* Miscellany. */
+ void (*pv_reboot)(char *bootstr);
+ void (*pv_printf)(__const__ char *fmt, ...);
+ void (*pv_abort)(void);
+ __volatile__ int *pv_ticks;
+ void (*pv_halt)(void);
+ void (**pv_synchook)(void);
+
+ /* Evaluate a forth string, not different proto for V0 and V2->up. */
+ union {
+ void (*v0_eval)(int len, char *str);
+ void (*v2_eval)(char *str);
+ } pv_fortheval;
+
+ struct linux_arguments_v0 **pv_v0bootargs;
+
+ /* Get ether address. */
+ unsigned int (*pv_enaddr)(int d, char *enaddr);
+
+ struct linux_bootargs_v2 pv_v2bootargs;
+ struct linux_dev_v2_funcs pv_v2devops;
+
+ int filler[15];
+
+ /* This one is sun4c/sun4 only. */
+ void (*pv_setctxt)(int ctxt, char *va, int pmeg);
+
+ /* Prom version 3 Multiprocessor routines. This stuff is crazy.
+ * No joke. Calling these when there is only one cpu probably
+ * crashes the machine, have to test this. :-)
+ */
+
+ /* v3_cpustart() will start the cpu 'whichcpu' in mmu-context
+ * 'thiscontext' executing at address 'prog_counter'
+ */
+ int (*v3_cpustart)(unsigned int whichcpu, int ctxtbl_ptr,
+ int thiscontext, char *prog_counter);
+
+ /* v3_cpustop() will cause cpu 'whichcpu' to stop executing
+ * until a resume cpu call is made.
+ */
+ int (*v3_cpustop)(unsigned int whichcpu);
+
+ /* v3_cpuidle() will idle cpu 'whichcpu' until a stop or
+ * resume cpu call is made.
+ */
+ int (*v3_cpuidle)(unsigned int whichcpu);
+
+ /* v3_cpuresume() will resume processor 'whichcpu' executing
+ * starting with whatever 'pc' and 'npc' were left at the
+ * last 'idle' or 'stop' call.
+ */
+ int (*v3_cpuresume)(unsigned int whichcpu);
+};
+
+/* Routines for traversing the prom device tree. */
+struct linux_nodeops {
+ phandle (*no_nextnode)(phandle node);
+ phandle (*no_child)(phandle node);
+ int (*no_proplen)(phandle node, const char *name);
+ int (*no_getprop)(phandle node, const char *name, char *val);
+ int (*no_setprop)(phandle node, const char *name, char *val, int len);
+ char * (*no_nextprop)(phandle node, char *name);
+};
+
+/* More fun PROM structures for device probing. */
+#if defined(__sparc__) && defined(__arch64__)
+#define PROMREG_MAX 24
+#define PROMVADDR_MAX 16
+#define PROMINTR_MAX 32
+#else
+#define PROMREG_MAX 16
+#define PROMVADDR_MAX 16
+#define PROMINTR_MAX 15
+#endif
+
+struct linux_prom_registers {
+ unsigned int which_io; /* hi part of physical address */
+ unsigned int phys_addr; /* The physical address of this register */
+ unsigned int reg_size; /* How many bytes does this register take up? */
+};
+
+struct linux_prom64_registers {
+ unsigned long phys_addr;
+ unsigned long reg_size;
+};
+
+struct linux_prom_irqs {
+ int pri; /* IRQ priority */
+ int vector; /* This is foobar, what does it do? */
+};
+
+/* Element of the "ranges" vector */
+struct linux_prom_ranges {
+ unsigned int ot_child_space;
+ unsigned int ot_child_base; /* Bus feels this */
+ unsigned int ot_parent_space;
+ unsigned int ot_parent_base; /* CPU looks from here */
+ unsigned int or_size;
+};
+
+/*
+ * Ranges and reg properties are a bit different for PCI.
+ */
+#if defined(__sparc__) && defined(__arch64__)
+struct linux_prom_pci_registers {
+ unsigned int phys_hi;
+ unsigned int phys_mid;
+ unsigned int phys_lo;
+
+ unsigned int size_hi;
+ unsigned int size_lo;
+};
+#else
+struct linux_prom_pci_registers {
+ /*
+ * We don't know what information this field contain.
+ * We guess, PCI device function is in bits 15:8
+ * So, ...
+ */
+ unsigned int which_io; /* Let it be which_io */
+
+ unsigned int phys_hi;
+ unsigned int phys_lo;
+
+ unsigned int size_hi;
+ unsigned int size_lo;
+};
+
+#endif
+
+struct linux_prom_pci_ranges {
+ unsigned int child_phys_hi; /* Only certain bits are encoded here. */
+ unsigned int child_phys_mid;
+ unsigned int child_phys_lo;
+
+ unsigned int parent_phys_hi;
+ unsigned int parent_phys_lo;
+
+ unsigned int size_hi;
+ unsigned int size_lo;
+};
+
+struct linux_prom_pci_intmap {
+ unsigned int phys_hi;
+ unsigned int phys_mid;
+ unsigned int phys_lo;
+
+ unsigned int interrupt;
+
+ int cnode;
+ unsigned int cinterrupt;
+};
+
+struct linux_prom_pci_intmask {
+ unsigned int phys_hi;
+ unsigned int phys_mid;
+ unsigned int phys_lo;
+ unsigned int interrupt;
+};
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* !(__SPARC_OPENPROM_H) */
diff --git a/arch/sparc/include/asm/oplib.h b/arch/sparc/include/asm/oplib.h
new file mode 100644
index 00000000000..72e04e13a6b
--- /dev/null
+++ b/arch/sparc/include/asm/oplib.h
@@ -0,0 +1,8 @@
+#ifndef ___ASM_SPARC_OPLIB_H
+#define ___ASM_SPARC_OPLIB_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/oplib_64.h>
+#else
+#include <asm/oplib_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/oplib_32.h b/arch/sparc/include/asm/oplib_32.h
new file mode 100644
index 00000000000..56a09b9d7b1
--- /dev/null
+++ b/arch/sparc/include/asm/oplib_32.h
@@ -0,0 +1,183 @@
+/*
+ * oplib.h: Describes the interface and available routines in the
+ * Linux Prom library.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef __SPARC_OPLIB_H
+#define __SPARC_OPLIB_H
+
+#include <asm/openprom.h>
+#include <linux/spinlock.h>
+#include <linux/compiler.h>
+
+/* The master romvec pointer... */
+extern struct linux_romvec *romvec;
+
+/* Enumeration to describe the prom major version we have detected. */
+enum prom_major_version {
+ PROM_V0, /* Original sun4c V0 prom */
+ PROM_V2, /* sun4c and early sun4m V2 prom */
+ PROM_V3, /* sun4m and later, up to sun4d/sun4e machines V3 */
+ PROM_P1275, /* IEEE compliant ISA based Sun PROM, only sun4u */
+};
+
+extern enum prom_major_version prom_vers;
+/* Revision, and firmware revision. */
+extern unsigned int prom_rev, prom_prev;
+
+/* Root node of the prom device tree, this stays constant after
+ * initialization is complete.
+ */
+extern phandle prom_root_node;
+
+/* Pointer to prom structure containing the device tree traversal
+ * and usage utility functions. Only prom-lib should use these,
+ * users use the interface defined by the library only!
+ */
+extern struct linux_nodeops *prom_nodeops;
+
+/* The functions... */
+
+/* You must call prom_init() before using any of the library services,
+ * preferably as early as possible. Pass it the romvec pointer.
+ */
+void prom_init(struct linux_romvec *rom_ptr);
+
+/* Boot argument acquisition, returns the boot command line string. */
+char *prom_getbootargs(void);
+
+/* Miscellaneous routines, don't really fit in any category per se. */
+
+/* Reboot the machine with the command line passed. */
+void prom_reboot(char *boot_command);
+
+/* Evaluate the forth string passed. */
+void prom_feval(char *forth_string);
+
+/* Enter the prom, with possibility of continuation with the 'go'
+ * command in newer proms.
+ */
+void prom_cmdline(void);
+
+/* Enter the prom, with no chance of continuation for the stand-alone
+ * which calls this.
+ */
+void __noreturn prom_halt(void);
+
+/* Set the PROM 'sync' callback function to the passed function pointer.
+ * When the user gives the 'sync' command at the prom prompt while the
+ * kernel is still active, the prom will call this routine.
+ *
+ * XXX The arguments are different on V0 vs. V2->higher proms, grrr! XXX
+ */
+typedef void (*sync_func_t)(void);
+void prom_setsync(sync_func_t func_ptr);
+
+/* Acquire the IDPROM of the root node in the prom device tree. This
+ * gets passed a buffer where you would like it stuffed. The return value
+ * is the format type of this idprom or 0xff on error.
+ */
+unsigned char prom_get_idprom(char *idp_buffer, int idpbuf_size);
+
+/* Get the prom major version. */
+int prom_version(void);
+
+/* Get the prom plugin revision. */
+int prom_getrev(void);
+
+/* Get the prom firmware revision. */
+int prom_getprev(void);
+
+/* Write a buffer of characters to the console. */
+void prom_console_write_buf(const char *buf, int len);
+
+/* Prom's internal routines, don't use in kernel/boot code. */
+__printf(1, 2) void prom_printf(const char *fmt, ...);
+void prom_write(const char *buf, unsigned int len);
+
+/* Multiprocessor operations... */
+
+/* Start the CPU with the given device tree node, context table, and context
+ * at the passed program counter.
+ */
+int prom_startcpu(int cpunode, struct linux_prom_registers *context_table,
+ int context, char *program_counter);
+
+/* Initialize the memory lists based upon the prom version. */
+void prom_meminit(void);
+
+/* PROM device tree traversal functions... */
+
+/* Get the child node of the given node, or zero if no child exists. */
+phandle prom_getchild(phandle parent_node);
+
+/* Get the next sibling node of the given node, or zero if no further
+ * siblings exist.
+ */
+phandle prom_getsibling(phandle node);
+
+/* Get the length, at the passed node, of the given property type.
+ * Returns -1 on error (ie. no such property at this node).
+ */
+int prom_getproplen(phandle thisnode, const char *property);
+
+/* Fetch the requested property using the given buffer. Returns
+ * the number of bytes the prom put into your buffer or -1 on error.
+ */
+int __must_check prom_getproperty(phandle thisnode, const char *property,
+ char *prop_buffer, int propbuf_size);
+
+/* Acquire an integer property. */
+int prom_getint(phandle node, char *property);
+
+/* Acquire an integer property, with a default value. */
+int prom_getintdefault(phandle node, char *property, int defval);
+
+/* Acquire a boolean property, 0=FALSE 1=TRUE. */
+int prom_getbool(phandle node, char *prop);
+
+/* Acquire a string property, null string on error. */
+void prom_getstring(phandle node, char *prop, char *buf, int bufsize);
+
+/* Search all siblings starting at the passed node for "name" matching
+ * the given string. Returns the node on success, zero on failure.
+ */
+phandle prom_searchsiblings(phandle node_start, char *name);
+
+/* Returns the next property after the passed property for the given
+ * node. Returns null string on failure.
+ */
+char *prom_nextprop(phandle node, char *prev_property, char *buffer);
+
+/* Returns phandle of the path specified */
+phandle prom_finddevice(char *name);
+
+/* Set the indicated property at the given node with the passed value.
+ * Returns the number of bytes of your value that the prom took.
+ */
+int prom_setprop(phandle node, const char *prop_name, char *prop_value,
+ int value_size);
+
+phandle prom_inst2pkg(int);
+
+/* Dorking with Bus ranges... */
+
+/* Apply promlib probes OBIO ranges to registers. */
+void prom_apply_obio_ranges(struct linux_prom_registers *obioregs, int nregs);
+
+/* Apply ranges of any prom node (and optionally parent node as well) to registers. */
+void prom_apply_generic_ranges(phandle node, phandle parent,
+ struct linux_prom_registers *sbusregs, int nregs);
+
+void prom_ranges_init(void);
+
+/* CPU probing helpers. */
+int cpu_find_by_instance(int instance, phandle *prom_node, int *mid);
+int cpu_find_by_mid(int mid, phandle *prom_node);
+int cpu_get_hwmid(phandle prom_node);
+
+extern spinlock_t prom_lock;
+
+#endif /* !(__SPARC_OPLIB_H) */
diff --git a/arch/sparc/include/asm/oplib_64.h b/arch/sparc/include/asm/oplib_64.h
new file mode 100644
index 00000000000..f34682430fc
--- /dev/null
+++ b/arch/sparc/include/asm/oplib_64.h
@@ -0,0 +1,250 @@
+/* oplib.h: Describes the interface and available routines in the
+ * Linux Prom library.
+ *
+ * Copyright (C) 1995, 2007 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+
+#ifndef __SPARC64_OPLIB_H
+#define __SPARC64_OPLIB_H
+
+#include <asm/openprom.h>
+
+/* OBP version string. */
+extern char prom_version[];
+
+/* Root node of the prom device tree, this stays constant after
+ * initialization is complete.
+ */
+extern phandle prom_root_node;
+
+/* PROM stdout */
+extern int prom_stdout;
+
+/* /chosen node of the prom device tree, this stays constant after
+ * initialization is complete.
+ */
+extern phandle prom_chosen_node;
+
+/* Helper values and strings in arch/sparc64/kernel/head.S */
+extern const char prom_peer_name[];
+extern const char prom_compatible_name[];
+extern const char prom_root_compatible[];
+extern const char prom_cpu_compatible[];
+extern const char prom_finddev_name[];
+extern const char prom_chosen_path[];
+extern const char prom_cpu_path[];
+extern const char prom_getprop_name[];
+extern const char prom_mmu_name[];
+extern const char prom_callmethod_name[];
+extern const char prom_translate_name[];
+extern const char prom_map_name[];
+extern const char prom_unmap_name[];
+extern int prom_mmu_ihandle_cache;
+extern unsigned int prom_boot_mapped_pc;
+extern unsigned int prom_boot_mapping_mode;
+extern unsigned long prom_boot_mapping_phys_high, prom_boot_mapping_phys_low;
+
+struct linux_mlist_p1275 {
+ struct linux_mlist_p1275 *theres_more;
+ unsigned long start_adr;
+ unsigned long num_bytes;
+};
+
+struct linux_mem_p1275 {
+ struct linux_mlist_p1275 **p1275_totphys;
+ struct linux_mlist_p1275 **p1275_prommap;
+ struct linux_mlist_p1275 **p1275_available; /* What we can use */
+};
+
+/* The functions... */
+
+/* You must call prom_init() before using any of the library services,
+ * preferably as early as possible. Pass it the romvec pointer.
+ */
+void prom_init(void *cif_handler, void *cif_stack);
+
+/* Boot argument acquisition, returns the boot command line string. */
+char *prom_getbootargs(void);
+
+/* Miscellaneous routines, don't really fit in any category per se. */
+
+/* Reboot the machine with the command line passed. */
+void prom_reboot(const char *boot_command);
+
+/* Evaluate the forth string passed. */
+void prom_feval(const char *forth_string);
+
+/* Enter the prom, with possibility of continuation with the 'go'
+ * command in newer proms.
+ */
+void prom_cmdline(void);
+
+/* Enter the prom, with no chance of continuation for the stand-alone
+ * which calls this.
+ */
+void prom_halt(void) __attribute__ ((noreturn));
+
+/* Halt and power-off the machine. */
+void prom_halt_power_off(void) __attribute__ ((noreturn));
+
+/* Acquire the IDPROM of the root node in the prom device tree. This
+ * gets passed a buffer where you would like it stuffed. The return value
+ * is the format type of this idprom or 0xff on error.
+ */
+unsigned char prom_get_idprom(char *idp_buffer, int idpbuf_size);
+
+/* Write a buffer of characters to the console. */
+void prom_console_write_buf(const char *buf, int len);
+
+/* Prom's internal routines, don't use in kernel/boot code. */
+__printf(1, 2) void prom_printf(const char *fmt, ...);
+void prom_write(const char *buf, unsigned int len);
+
+/* Multiprocessor operations... */
+#ifdef CONFIG_SMP
+/* Start the CPU with the given device tree node at the passed program
+ * counter with the given arg passed in via register %o0.
+ */
+void prom_startcpu(int cpunode, unsigned long pc, unsigned long arg);
+
+/* Start the CPU with the given cpu ID at the passed program
+ * counter with the given arg passed in via register %o0.
+ */
+void prom_startcpu_cpuid(int cpuid, unsigned long pc, unsigned long arg);
+
+/* Stop the CPU with the given cpu ID. */
+void prom_stopcpu_cpuid(int cpuid);
+
+/* Stop the current CPU. */
+void prom_stopself(void);
+
+/* Idle the current CPU. */
+void prom_idleself(void);
+
+/* Resume the CPU with the passed device tree node. */
+void prom_resumecpu(int cpunode);
+#endif
+
+/* Power management interfaces. */
+
+/* Put the current CPU to sleep. */
+void prom_sleepself(void);
+
+/* Put the entire system to sleep. */
+int prom_sleepsystem(void);
+
+/* Initiate a wakeup event. */
+int prom_wakeupsystem(void);
+
+/* MMU and memory related OBP interfaces. */
+
+/* Get unique string identifying SIMM at given physical address. */
+int prom_getunumber(int syndrome_code,
+ unsigned long phys_addr,
+ char *buf, int buflen);
+
+/* Retain physical memory to the caller across soft resets. */
+int prom_retain(const char *name, unsigned long size,
+ unsigned long align, unsigned long *paddr);
+
+/* Load explicit I/D TLB entries into the calling processor. */
+long prom_itlb_load(unsigned long index,
+ unsigned long tte_data,
+ unsigned long vaddr);
+
+long prom_dtlb_load(unsigned long index,
+ unsigned long tte_data,
+ unsigned long vaddr);
+
+/* Map/Unmap client program address ranges. First the format of
+ * the mapping mode argument.
+ */
+#define PROM_MAP_WRITE 0x0001 /* Writable */
+#define PROM_MAP_READ 0x0002 /* Readable - sw */
+#define PROM_MAP_EXEC 0x0004 /* Executable - sw */
+#define PROM_MAP_LOCKED 0x0010 /* Locked, use i/dtlb load calls for this instead */
+#define PROM_MAP_CACHED 0x0020 /* Cacheable in both L1 and L2 caches */
+#define PROM_MAP_SE 0x0040 /* Side-Effects */
+#define PROM_MAP_GLOB 0x0080 /* Global */
+#define PROM_MAP_IE 0x0100 /* Invert-Endianness */
+#define PROM_MAP_DEFAULT (PROM_MAP_WRITE | PROM_MAP_READ | PROM_MAP_EXEC | PROM_MAP_CACHED)
+
+int prom_map(int mode, unsigned long size,
+ unsigned long vaddr, unsigned long paddr);
+void prom_unmap(unsigned long size, unsigned long vaddr);
+
+
+/* PROM device tree traversal functions... */
+
+/* Get the child node of the given node, or zero if no child exists. */
+phandle prom_getchild(phandle parent_node);
+
+/* Get the next sibling node of the given node, or zero if no further
+ * siblings exist.
+ */
+phandle prom_getsibling(phandle node);
+
+/* Get the length, at the passed node, of the given property type.
+ * Returns -1 on error (ie. no such property at this node).
+ */
+int prom_getproplen(phandle thisnode, const char *property);
+
+/* Fetch the requested property using the given buffer. Returns
+ * the number of bytes the prom put into your buffer or -1 on error.
+ */
+int prom_getproperty(phandle thisnode, const char *property,
+ char *prop_buffer, int propbuf_size);
+
+/* Acquire an integer property. */
+int prom_getint(phandle node, const char *property);
+
+/* Acquire an integer property, with a default value. */
+int prom_getintdefault(phandle node, const char *property, int defval);
+
+/* Acquire a boolean property, 0=FALSE 1=TRUE. */
+int prom_getbool(phandle node, const char *prop);
+
+/* Acquire a string property, null string on error. */
+void prom_getstring(phandle node, const char *prop, char *buf,
+ int bufsize);
+
+/* Does the passed node have the given "name"? YES=1 NO=0 */
+int prom_nodematch(phandle thisnode, const char *name);
+
+/* Search all siblings starting at the passed node for "name" matching
+ * the given string. Returns the node on success, zero on failure.
+ */
+phandle prom_searchsiblings(phandle node_start, const char *name);
+
+/* Return the first property type, as a string, for the given node.
+ * Returns a null string on error. Buffer should be at least 32B long.
+ */
+char *prom_firstprop(phandle node, char *buffer);
+
+/* Returns the next property after the passed property for the given
+ * node. Returns null string on failure. Buffer should be at least 32B long.
+ */
+char *prom_nextprop(phandle node, const char *prev_property, char *buf);
+
+/* Returns 1 if the specified node has given property. */
+int prom_node_has_property(phandle node, const char *property);
+
+/* Returns phandle of the path specified */
+phandle prom_finddevice(const char *name);
+
+/* Set the indicated property at the given node with the passed value.
+ * Returns the number of bytes of your value that the prom took.
+ */
+int prom_setprop(phandle node, const char *prop_name, char *prop_value,
+ int value_size);
+
+phandle prom_inst2pkg(int);
+void prom_sun4v_guest_soft_state(void);
+
+int prom_ihandle2path(int handle, char *buffer, int bufsize);
+
+/* Client interface level routines. */
+void p1275_cmd_direct(unsigned long *);
+
+#endif /* !(__SPARC64_OPLIB_H) */
diff --git a/arch/sparc/include/asm/page.h b/arch/sparc/include/asm/page.h
new file mode 100644
index 00000000000..1be2fdec626
--- /dev/null
+++ b/arch/sparc/include/asm/page.h
@@ -0,0 +1,11 @@
+#ifndef ___ASM_SPARC_PAGE_H
+#define ___ASM_SPARC_PAGE_H
+
+#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
+
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/page_64.h>
+#else
+#include <asm/page_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/page_32.h b/arch/sparc/include/asm/page_32.h
new file mode 100644
index 00000000000..f82a1f36b65
--- /dev/null
+++ b/arch/sparc/include/asm/page_32.h
@@ -0,0 +1,141 @@
+/*
+ * page.h: Various defines and such for MMU operations on the Sparc for
+ * the Linux kernel.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _SPARC_PAGE_H
+#define _SPARC_PAGE_H
+
+#include <linux/const.h>
+
+#define PAGE_SHIFT 12
+#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
+#define PAGE_MASK (~(PAGE_SIZE-1))
+
+#ifndef __ASSEMBLY__
+
+#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE)
+#define copy_page(to,from) memcpy((void *)(to), (void *)(from), PAGE_SIZE)
+#define clear_user_page(addr, vaddr, page) \
+ do { clear_page(addr); \
+ sparc_flush_page_to_ram(page); \
+ } while (0)
+#define copy_user_page(to, from, vaddr, page) \
+ do { copy_page(to, from); \
+ sparc_flush_page_to_ram(page); \
+ } while (0)
+
+/* The following structure is used to hold the physical
+ * memory configuration of the machine. This is filled in
+ * prom_meminit() and is later used by mem_init() to set up
+ * mem_map[]. We statically allocate SPARC_PHYS_BANKS+1 of
+ * these structs, this is arbitrary. The entry after the
+ * last valid one has num_bytes==0.
+ */
+struct sparc_phys_banks {
+ unsigned long base_addr;
+ unsigned long num_bytes;
+};
+
+#define SPARC_PHYS_BANKS 32
+
+extern struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS+1];
+
+/* passing structs on the Sparc slow us down tremendously... */
+
+/* #define STRICT_MM_TYPECHECKS */
+
+#ifdef STRICT_MM_TYPECHECKS
+/*
+ * These are used to make use of C type-checking..
+ */
+typedef struct { unsigned long pte; } pte_t;
+typedef struct { unsigned long iopte; } iopte_t;
+typedef struct { unsigned long pmdv[16]; } pmd_t;
+typedef struct { unsigned long pgd; } pgd_t;
+typedef struct { unsigned long ctxd; } ctxd_t;
+typedef struct { unsigned long pgprot; } pgprot_t;
+typedef struct { unsigned long iopgprot; } iopgprot_t;
+
+#define pte_val(x) ((x).pte)
+#define iopte_val(x) ((x).iopte)
+#define pmd_val(x) ((x).pmdv[0])
+#define pgd_val(x) ((x).pgd)
+#define ctxd_val(x) ((x).ctxd)
+#define pgprot_val(x) ((x).pgprot)
+#define iopgprot_val(x) ((x).iopgprot)
+
+#define __pte(x) ((pte_t) { (x) } )
+#define __iopte(x) ((iopte_t) { (x) } )
+/* #define __pmd(x) ((pmd_t) { (x) } ) */ /* XXX procedure with loop */
+#define __pgd(x) ((pgd_t) { (x) } )
+#define __ctxd(x) ((ctxd_t) { (x) } )
+#define __pgprot(x) ((pgprot_t) { (x) } )
+#define __iopgprot(x) ((iopgprot_t) { (x) } )
+
+#else
+/*
+ * .. while these make it easier on the compiler
+ */
+typedef unsigned long pte_t;
+typedef unsigned long iopte_t;
+typedef struct { unsigned long pmdv[16]; } pmd_t;
+typedef unsigned long pgd_t;
+typedef unsigned long ctxd_t;
+typedef unsigned long pgprot_t;
+typedef unsigned long iopgprot_t;
+
+#define pte_val(x) (x)
+#define iopte_val(x) (x)
+#define pmd_val(x) ((x).pmdv[0])
+#define pgd_val(x) (x)
+#define ctxd_val(x) (x)
+#define pgprot_val(x) (x)
+#define iopgprot_val(x) (x)
+
+#define __pte(x) (x)
+#define __iopte(x) (x)
+/* #define __pmd(x) (x) */ /* XXX later */
+#define __pgd(x) (x)
+#define __ctxd(x) (x)
+#define __pgprot(x) (x)
+#define __iopgprot(x) (x)
+
+#endif
+
+typedef struct page *pgtable_t;
+
+#define TASK_UNMAPPED_BASE 0x50000000
+
+#else /* !(__ASSEMBLY__) */
+
+#define __pgprot(x) (x)
+
+#endif /* !(__ASSEMBLY__) */
+
+#define PAGE_OFFSET 0xf0000000
+#ifndef __ASSEMBLY__
+extern unsigned long phys_base;
+extern unsigned long pfn_base;
+#endif
+#define __pa(x) ((unsigned long)(x) - PAGE_OFFSET + phys_base)
+#define __va(x) ((void *)((unsigned long) (x) - phys_base + PAGE_OFFSET))
+
+#define virt_to_phys __pa
+#define phys_to_virt __va
+
+#define ARCH_PFN_OFFSET (pfn_base)
+#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
+
+#define pfn_valid(pfn) (((pfn) >= (pfn_base)) && (((pfn)-(pfn_base)) < max_mapnr))
+#define virt_addr_valid(kaddr) ((((unsigned long)(kaddr)-PAGE_OFFSET)>>PAGE_SHIFT) < max_mapnr)
+
+#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
+ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
+#include <asm-generic/memory_model.h>
+#include <asm-generic/getorder.h>
+
+#endif /* _SPARC_PAGE_H */
diff --git a/arch/sparc/include/asm/page_64.h b/arch/sparc/include/asm/page_64.h
new file mode 100644
index 00000000000..bf109984a03
--- /dev/null
+++ b/arch/sparc/include/asm/page_64.h
@@ -0,0 +1,159 @@
+#ifndef _SPARC64_PAGE_H
+#define _SPARC64_PAGE_H
+
+#include <linux/const.h>
+
+#define PAGE_SHIFT 13
+
+#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
+#define PAGE_MASK (~(PAGE_SIZE-1))
+
+/* Flushing for D-cache alias handling is only needed if
+ * the page size is smaller than 16K.
+ */
+#if PAGE_SHIFT < 14
+#define DCACHE_ALIASING_POSSIBLE
+#endif
+
+#define HPAGE_SHIFT 23
+#define REAL_HPAGE_SHIFT 22
+
+#define REAL_HPAGE_SIZE (_AC(1,UL) << REAL_HPAGE_SHIFT)
+
+#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
+#define HPAGE_SIZE (_AC(1,UL) << HPAGE_SHIFT)
+#define HPAGE_MASK (~(HPAGE_SIZE - 1UL))
+#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
+#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
+#endif
+
+#ifndef __ASSEMBLY__
+
+#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
+struct pt_regs;
+void hugetlb_setup(struct pt_regs *regs);
+#endif
+
+#define WANT_PAGE_VIRTUAL
+
+void _clear_page(void *page);
+#define clear_page(X) _clear_page((void *)(X))
+struct page;
+void clear_user_page(void *addr, unsigned long vaddr, struct page *page);
+#define copy_page(X,Y) memcpy((void *)(X), (void *)(Y), PAGE_SIZE)
+void copy_user_page(void *to, void *from, unsigned long vaddr, struct page *topage);
+
+/* Unlike sparc32, sparc64's parameter passing API is more
+ * sane in that structures which as small enough are passed
+ * in registers instead of on the stack. Thus, setting
+ * STRICT_MM_TYPECHECKS does not generate worse code so
+ * let's enable it to get the type checking.
+ */
+
+#define STRICT_MM_TYPECHECKS
+
+#ifdef STRICT_MM_TYPECHECKS
+/* These are used to make use of C type-checking.. */
+typedef struct { unsigned long pte; } pte_t;
+typedef struct { unsigned long iopte; } iopte_t;
+typedef struct { unsigned long pmd; } pmd_t;
+typedef struct { unsigned long pgd; } pgd_t;
+typedef struct { unsigned long pgprot; } pgprot_t;
+
+#define pte_val(x) ((x).pte)
+#define iopte_val(x) ((x).iopte)
+#define pmd_val(x) ((x).pmd)
+#define pgd_val(x) ((x).pgd)
+#define pgprot_val(x) ((x).pgprot)
+
+#define __pte(x) ((pte_t) { (x) } )
+#define __iopte(x) ((iopte_t) { (x) } )
+#define __pmd(x) ((pmd_t) { (x) } )
+#define __pgd(x) ((pgd_t) { (x) } )
+#define __pgprot(x) ((pgprot_t) { (x) } )
+
+#else
+/* .. while these make it easier on the compiler */
+typedef unsigned long pte_t;
+typedef unsigned long iopte_t;
+typedef unsigned long pmd_t;
+typedef unsigned long pgd_t;
+typedef unsigned long pgprot_t;
+
+#define pte_val(x) (x)
+#define iopte_val(x) (x)
+#define pmd_val(x) (x)
+#define pgd_val(x) (x)
+#define pgprot_val(x) (x)
+
+#define __pte(x) (x)
+#define __iopte(x) (x)
+#define __pmd(x) (x)
+#define __pgd(x) (x)
+#define __pgprot(x) (x)
+
+#endif /* (STRICT_MM_TYPECHECKS) */
+
+typedef pte_t *pgtable_t;
+
+/* These two values define the virtual address space range in which we
+ * must forbid 64-bit user processes from making mappings. It used to
+ * represent precisely the virtual address space hole present in most
+ * early sparc64 chips including UltraSPARC-I. But now it also is
+ * further constrained by the limits of our page tables, which is
+ * 43-bits of virtual address.
+ */
+#define SPARC64_VA_HOLE_TOP _AC(0xfffffc0000000000,UL)
+#define SPARC64_VA_HOLE_BOTTOM _AC(0x0000040000000000,UL)
+
+/* The next two defines specify the actual exclusion region we
+ * enforce, wherein we use a 4GB red zone on each side of the VA hole.
+ */
+#define VA_EXCLUDE_START (SPARC64_VA_HOLE_BOTTOM - (1UL << 32UL))
+#define VA_EXCLUDE_END (SPARC64_VA_HOLE_TOP + (1UL << 32UL))
+
+#define TASK_UNMAPPED_BASE (test_thread_flag(TIF_32BIT) ? \
+ _AC(0x0000000070000000,UL) : \
+ VA_EXCLUDE_END)
+
+#include <asm-generic/memory_model.h>
+
+#define PAGE_OFFSET_BY_BITS(X) (-(_AC(1,UL) << (X)))
+extern unsigned long PAGE_OFFSET;
+
+#endif /* !(__ASSEMBLY__) */
+
+/* The maximum number of physical memory address bits we support, this
+ * is used to size various tables used to manage kernel TLB misses and
+ * also the sparsemem code.
+ */
+#define MAX_PHYS_ADDRESS_BITS 47
+
+/* These two shift counts are used when indexing sparc64_valid_addr_bitmap
+ * and kpte_linear_bitmap.
+ */
+#define ILOG2_4MB 22
+#define ILOG2_256MB 28
+
+#ifndef __ASSEMBLY__
+
+#define __pa(x) ((unsigned long)(x) - PAGE_OFFSET)
+#define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET))
+
+#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
+
+#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr)>>PAGE_SHIFT)
+
+#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
+
+#define virt_to_phys __pa
+#define phys_to_virt __va
+
+#endif /* !(__ASSEMBLY__) */
+
+#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
+ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
+#include <asm-generic/getorder.h>
+
+#endif /* _SPARC64_PAGE_H */
diff --git a/arch/sparc/include/asm/parport.h b/arch/sparc/include/asm/parport.h
new file mode 100644
index 00000000000..c55291e5b83
--- /dev/null
+++ b/arch/sparc/include/asm/parport.h
@@ -0,0 +1,253 @@
+/* parport.h: sparc64 specific parport initialization and dma.
+ *
+ * Copyright (C) 1999 Eddie C. Dost (ecd@skynet.be)
+ */
+
+#ifndef _ASM_SPARC64_PARPORT_H
+#define _ASM_SPARC64_PARPORT_H 1
+
+#include <linux/of_device.h>
+
+#include <asm/ebus_dma.h>
+#include <asm/ns87303.h>
+#include <asm/prom.h>
+
+#define PARPORT_PC_MAX_PORTS PARPORT_MAX
+
+/*
+ * While sparc64 doesn't have an ISA DMA API, we provide something that looks
+ * close enough to make parport_pc happy
+ */
+#define HAS_DMA
+
+static DEFINE_SPINLOCK(dma_spin_lock);
+
+#define claim_dma_lock() \
+({ unsigned long flags; \
+ spin_lock_irqsave(&dma_spin_lock, flags); \
+ flags; \
+})
+
+#define release_dma_lock(__flags) \
+ spin_unlock_irqrestore(&dma_spin_lock, __flags);
+
+static struct sparc_ebus_info {
+ struct ebus_dma_info info;
+ unsigned int addr;
+ unsigned int count;
+ int lock;
+
+ struct parport *port;
+} sparc_ebus_dmas[PARPORT_PC_MAX_PORTS];
+
+static DECLARE_BITMAP(dma_slot_map, PARPORT_PC_MAX_PORTS);
+
+static inline int request_dma(unsigned int dmanr, const char *device_id)
+{
+ if (dmanr >= PARPORT_PC_MAX_PORTS)
+ return -EINVAL;
+ if (xchg(&sparc_ebus_dmas[dmanr].lock, 1) != 0)
+ return -EBUSY;
+ return 0;
+}
+
+static inline void free_dma(unsigned int dmanr)
+{
+ if (dmanr >= PARPORT_PC_MAX_PORTS) {
+ printk(KERN_WARNING "Trying to free DMA%d\n", dmanr);
+ return;
+ }
+ if (xchg(&sparc_ebus_dmas[dmanr].lock, 0) == 0) {
+ printk(KERN_WARNING "Trying to free free DMA%d\n", dmanr);
+ return;
+ }
+}
+
+static inline void enable_dma(unsigned int dmanr)
+{
+ ebus_dma_enable(&sparc_ebus_dmas[dmanr].info, 1);
+
+ if (ebus_dma_request(&sparc_ebus_dmas[dmanr].info,
+ sparc_ebus_dmas[dmanr].addr,
+ sparc_ebus_dmas[dmanr].count))
+ BUG();
+}
+
+static inline void disable_dma(unsigned int dmanr)
+{
+ ebus_dma_enable(&sparc_ebus_dmas[dmanr].info, 0);
+}
+
+static inline void clear_dma_ff(unsigned int dmanr)
+{
+ /* nothing */
+}
+
+static inline void set_dma_mode(unsigned int dmanr, char mode)
+{
+ ebus_dma_prepare(&sparc_ebus_dmas[dmanr].info, (mode != DMA_MODE_WRITE));
+}
+
+static inline void set_dma_addr(unsigned int dmanr, unsigned int addr)
+{
+ sparc_ebus_dmas[dmanr].addr = addr;
+}
+
+static inline void set_dma_count(unsigned int dmanr, unsigned int count)
+{
+ sparc_ebus_dmas[dmanr].count = count;
+}
+
+static inline unsigned int get_dma_residue(unsigned int dmanr)
+{
+ return ebus_dma_residue(&sparc_ebus_dmas[dmanr].info);
+}
+
+static int ecpp_probe(struct platform_device *op)
+{
+ unsigned long base = op->resource[0].start;
+ unsigned long config = op->resource[1].start;
+ unsigned long d_base = op->resource[2].start;
+ unsigned long d_len;
+ struct device_node *parent;
+ struct parport *p;
+ int slot, err;
+
+ parent = op->dev.of_node->parent;
+ if (!strcmp(parent->name, "dma")) {
+ p = parport_pc_probe_port(base, base + 0x400,
+ op->archdata.irqs[0], PARPORT_DMA_NOFIFO,
+ op->dev.parent->parent, 0);
+ if (!p)
+ return -ENOMEM;
+ dev_set_drvdata(&op->dev, p);
+ return 0;
+ }
+
+ for (slot = 0; slot < PARPORT_PC_MAX_PORTS; slot++) {
+ if (!test_and_set_bit(slot, dma_slot_map))
+ break;
+ }
+ err = -ENODEV;
+ if (slot >= PARPORT_PC_MAX_PORTS)
+ goto out_err;
+
+ spin_lock_init(&sparc_ebus_dmas[slot].info.lock);
+
+ d_len = (op->resource[2].end - d_base) + 1UL;
+ sparc_ebus_dmas[slot].info.regs =
+ of_ioremap(&op->resource[2], 0, d_len, "ECPP DMA");
+
+ if (!sparc_ebus_dmas[slot].info.regs)
+ goto out_clear_map;
+
+ sparc_ebus_dmas[slot].info.flags = 0;
+ sparc_ebus_dmas[slot].info.callback = NULL;
+ sparc_ebus_dmas[slot].info.client_cookie = NULL;
+ sparc_ebus_dmas[slot].info.irq = 0xdeadbeef;
+ strcpy(sparc_ebus_dmas[slot].info.name, "parport");
+ if (ebus_dma_register(&sparc_ebus_dmas[slot].info))
+ goto out_unmap_regs;
+
+ ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 1);
+
+ /* Configure IRQ to Push Pull, Level Low */
+ /* Enable ECP, set bit 2 of the CTR first */
+ outb(0x04, base + 0x02);
+ ns87303_modify(config, PCR,
+ PCR_EPP_ENABLE |
+ PCR_IRQ_ODRAIN,
+ PCR_ECP_ENABLE |
+ PCR_ECP_CLK_ENA |
+ PCR_IRQ_POLAR);
+
+ /* CTR bit 5 controls direction of port */
+ ns87303_modify(config, PTR,
+ 0, PTR_LPT_REG_DIR);
+
+ p = parport_pc_probe_port(base, base + 0x400,
+ op->archdata.irqs[0],
+ slot,
+ op->dev.parent,
+ 0);
+ err = -ENOMEM;
+ if (!p)
+ goto out_disable_irq;
+
+ dev_set_drvdata(&op->dev, p);
+
+ return 0;
+
+out_disable_irq:
+ ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 0);
+ ebus_dma_unregister(&sparc_ebus_dmas[slot].info);
+
+out_unmap_regs:
+ of_iounmap(&op->resource[2], sparc_ebus_dmas[slot].info.regs, d_len);
+
+out_clear_map:
+ clear_bit(slot, dma_slot_map);
+
+out_err:
+ return err;
+}
+
+static int ecpp_remove(struct platform_device *op)
+{
+ struct parport *p = dev_get_drvdata(&op->dev);
+ int slot = p->dma;
+
+ parport_pc_unregister_port(p);
+
+ if (slot != PARPORT_DMA_NOFIFO) {
+ unsigned long d_base = op->resource[2].start;
+ unsigned long d_len;
+
+ d_len = (op->resource[2].end - d_base) + 1UL;
+
+ ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 0);
+ ebus_dma_unregister(&sparc_ebus_dmas[slot].info);
+ of_iounmap(&op->resource[2],
+ sparc_ebus_dmas[slot].info.regs,
+ d_len);
+ clear_bit(slot, dma_slot_map);
+ }
+
+ return 0;
+}
+
+static const struct of_device_id ecpp_match[] = {
+ {
+ .name = "ecpp",
+ },
+ {
+ .name = "parallel",
+ .compatible = "ecpp",
+ },
+ {
+ .name = "parallel",
+ .compatible = "ns87317-ecpp",
+ },
+ {
+ .name = "parallel",
+ .compatible = "pnpALI,1533,3",
+ },
+ {},
+};
+
+static struct platform_driver ecpp_driver = {
+ .driver = {
+ .name = "ecpp",
+ .owner = THIS_MODULE,
+ .of_match_table = ecpp_match,
+ },
+ .probe = ecpp_probe,
+ .remove = ecpp_remove,
+};
+
+static int parport_pc_find_nonpci_ports(int autoirq, int autodma)
+{
+ return platform_driver_register(&ecpp_driver);
+}
+
+#endif /* !(_ASM_SPARC64_PARPORT_H */
diff --git a/arch/sparc/include/asm/pbm.h b/arch/sparc/include/asm/pbm.h
new file mode 100644
index 00000000000..458a4916d14
--- /dev/null
+++ b/arch/sparc/include/asm/pbm.h
@@ -0,0 +1,47 @@
+/*
+ *
+ * pbm.h: PCI bus module pseudo driver software state
+ * Adopted from sparc64 by V. Roganov and G. Raiko
+ *
+ * Original header:
+ * pbm.h: U2P PCI bus module pseudo driver software state.
+ *
+ * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ *
+ * To put things into perspective, consider sparc64 with a few PCI controllers.
+ * Each type would have an own structure, with instances related one to one.
+ * We have only pcic on sparc, but we want to be compatible with sparc64 pbm.h.
+ * All three represent different abstractions.
+ * pci_bus - Linux PCI subsystem view of a PCI bus (including bridged buses)
+ * pbm - Arch-specific view of a PCI bus (sparc or sparc64)
+ * pcic - Chip-specific information for PCIC.
+ */
+
+#ifndef __SPARC_PBM_H
+#define __SPARC_PBM_H
+
+#include <linux/pci.h>
+#include <asm/oplib.h>
+#include <asm/prom.h>
+
+struct linux_pbm_info {
+ int prom_node;
+ char prom_name[64];
+ /* struct linux_prom_pci_ranges pbm_ranges[PROMREG_MAX]; */
+ /* int num_pbm_ranges; */
+
+ /* Now things for the actual PCI bus probes. */
+ unsigned int pci_first_busno; /* Can it be nonzero? */
+ struct pci_bus *pci_bus; /* Was inline, MJ allocs now */
+};
+
+/* PCI devices which are not bridges have this placed in their pci_dev
+ * sysdata member. This makes OBP aware PCI device drivers easier to
+ * code.
+ */
+struct pcidev_cookie {
+ struct linux_pbm_info *pbm;
+ struct device_node *prom_node;
+};
+
+#endif /* !(__SPARC_PBM_H) */
diff --git a/arch/sparc/include/asm/pci.h b/arch/sparc/include/asm/pci.h
new file mode 100644
index 00000000000..d9c031f9910
--- /dev/null
+++ b/arch/sparc/include/asm/pci.h
@@ -0,0 +1,11 @@
+#ifndef ___ASM_SPARC_PCI_H
+#define ___ASM_SPARC_PCI_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/pci_64.h>
+#else
+#include <asm/pci_32.h>
+#endif
+
+#include <asm-generic/pci-dma-compat.h>
+
+#endif
diff --git a/arch/sparc/include/asm/pci_32.h b/arch/sparc/include/asm/pci_32.h
new file mode 100644
index 00000000000..53e9b4987db
--- /dev/null
+++ b/arch/sparc/include/asm/pci_32.h
@@ -0,0 +1,56 @@
+#ifndef __SPARC_PCI_H
+#define __SPARC_PCI_H
+
+#ifdef __KERNEL__
+
+#include <linux/dma-mapping.h>
+
+/* Can be used to override the logic in pci_scan_bus for skipping
+ * already-configured bus numbers - to be used for buggy BIOSes
+ * or architectures with incomplete PCI setup by the loader.
+ */
+#define pcibios_assign_all_busses() 0
+
+#define PCIBIOS_MIN_IO 0UL
+#define PCIBIOS_MIN_MEM 0UL
+
+#define PCI_IRQ_NONE 0xffffffff
+
+/* Dynamic DMA mapping stuff.
+ */
+#define PCI_DMA_BUS_IS_PHYS (0)
+
+struct pci_dev;
+
+#ifdef CONFIG_PCI
+static inline void pci_dma_burst_advice(struct pci_dev *pdev,
+ enum pci_dma_burst_strategy *strat,
+ unsigned long *strategy_parameter)
+{
+ *strat = PCI_DMA_BURST_INFINITY;
+ *strategy_parameter = ~0UL;
+}
+#endif
+
+#endif /* __KERNEL__ */
+
+#ifndef CONFIG_LEON_PCI
+/* generic pci stuff */
+#include <asm-generic/pci.h>
+#else
+/*
+ * On LEON PCI Memory space is mapped 1:1 with physical address space.
+ *
+ * I/O space is located at low 64Kbytes in PCI I/O space. The I/O addresses
+ * are converted into CPU addresses to virtual addresses that are mapped with
+ * MMU to the PCI Host PCI I/O space window which are translated to the low
+ * 64Kbytes by the Host controller.
+ */
+
+static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
+{
+ return PCI_IRQ_NONE;
+}
+#endif
+
+#endif /* __SPARC_PCI_H */
diff --git a/arch/sparc/include/asm/pci_64.h b/arch/sparc/include/asm/pci_64.h
new file mode 100644
index 00000000000..bd00a622616
--- /dev/null
+++ b/arch/sparc/include/asm/pci_64.h
@@ -0,0 +1,82 @@
+#ifndef __SPARC64_PCI_H
+#define __SPARC64_PCI_H
+
+#ifdef __KERNEL__
+
+#include <linux/dma-mapping.h>
+
+/* Can be used to override the logic in pci_scan_bus for skipping
+ * already-configured bus numbers - to be used for buggy BIOSes
+ * or architectures with incomplete PCI setup by the loader.
+ */
+#define pcibios_assign_all_busses() 0
+
+#define PCIBIOS_MIN_IO 0UL
+#define PCIBIOS_MIN_MEM 0UL
+
+#define PCI_IRQ_NONE 0xffffffff
+
+/* The PCI address space does not equal the physical memory
+ * address space. The networking and block device layers use
+ * this boolean for bounce buffer decisions.
+ */
+#define PCI_DMA_BUS_IS_PHYS (0)
+
+/* PCI IOMMU mapping bypass support. */
+
+/* PCI 64-bit addressing works for all slots on all controller
+ * types on sparc64. However, it requires that the device
+ * can drive enough of the 64 bits.
+ */
+#define PCI64_REQUIRED_MASK (~(u64)0)
+#define PCI64_ADDR_BASE 0xfffc000000000000UL
+
+#ifdef CONFIG_PCI
+static inline void pci_dma_burst_advice(struct pci_dev *pdev,
+ enum pci_dma_burst_strategy *strat,
+ unsigned long *strategy_parameter)
+{
+ unsigned long cacheline_size;
+ u8 byte;
+
+ pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &byte);
+ if (byte == 0)
+ cacheline_size = 1024;
+ else
+ cacheline_size = (int) byte * 4;
+
+ *strat = PCI_DMA_BURST_BOUNDARY;
+ *strategy_parameter = cacheline_size;
+}
+#endif
+
+/* Return the index of the PCI controller for device PDEV. */
+
+int pci_domain_nr(struct pci_bus *bus);
+static inline int pci_proc_domain(struct pci_bus *bus)
+{
+ return 1;
+}
+
+/* Platform support for /proc/bus/pci/X/Y mmap()s. */
+
+#define HAVE_PCI_MMAP
+#define HAVE_ARCH_PCI_GET_UNMAPPED_AREA
+#define get_pci_unmapped_area get_fb_unmapped_area
+
+int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+ enum pci_mmap_state mmap_state,
+ int write_combine);
+
+static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
+{
+ return PCI_IRQ_NONE;
+}
+
+#define HAVE_ARCH_PCI_RESOURCE_TO_USER
+void pci_resource_to_user(const struct pci_dev *dev, int bar,
+ const struct resource *rsrc,
+ resource_size_t *start, resource_size_t *end);
+#endif /* __KERNEL__ */
+
+#endif /* __SPARC64_PCI_H */
diff --git a/arch/sparc/include/asm/pcic.h b/arch/sparc/include/asm/pcic.h
new file mode 100644
index 00000000000..f4170679259
--- /dev/null
+++ b/arch/sparc/include/asm/pcic.h
@@ -0,0 +1,129 @@
+/*
+ * pcic.h: JavaEngine 1 specific PCI definitions.
+ *
+ * Copyright (C) 1998 V. Roganov and G. Raiko
+ */
+
+#ifndef __SPARC_PCIC_H
+#define __SPARC_PCIC_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+#include <linux/smp.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <asm/pbm.h>
+
+struct linux_pcic {
+ void __iomem *pcic_regs;
+ unsigned long pcic_io;
+ void __iomem *pcic_config_space_addr;
+ void __iomem *pcic_config_space_data;
+ struct resource pcic_res_regs;
+ struct resource pcic_res_io;
+ struct resource pcic_res_cfg_addr;
+ struct resource pcic_res_cfg_data;
+ struct linux_pbm_info pbm;
+ struct pcic_ca2irq *pcic_imap;
+ int pcic_imdim;
+};
+
+#ifdef CONFIG_PCIC_PCI
+int pcic_present(void);
+int pcic_probe(void);
+void pci_time_init(void);
+void sun4m_pci_init_IRQ(void);
+#else
+static inline int pcic_present(void) { return 0; }
+static inline int pcic_probe(void) { return 0; }
+static inline void pci_time_init(void) {}
+static inline void sun4m_pci_init_IRQ(void) {}
+#endif
+#endif
+
+/* Size of PCI I/O space which we relocate. */
+#define PCI_SPACE_SIZE 0x1000000 /* 16 MB */
+
+/* PCIC Register Set. */
+#define PCI_DIAGNOSTIC_0 0x40 /* 32 bits */
+#define PCI_SIZE_0 0x44 /* 32 bits */
+#define PCI_SIZE_1 0x48 /* 32 bits */
+#define PCI_SIZE_2 0x4c /* 32 bits */
+#define PCI_SIZE_3 0x50 /* 32 bits */
+#define PCI_SIZE_4 0x54 /* 32 bits */
+#define PCI_SIZE_5 0x58 /* 32 bits */
+#define PCI_PIO_CONTROL 0x60 /* 8 bits */
+#define PCI_DVMA_CONTROL 0x62 /* 8 bits */
+#define PCI_DVMA_CONTROL_INACTIVITY_REQ (1<<0)
+#define PCI_DVMA_CONTROL_IOTLB_ENABLE (1<<0)
+#define PCI_DVMA_CONTROL_IOTLB_DISABLE 0
+#define PCI_DVMA_CONTROL_INACTIVITY_ACK (1<<4)
+#define PCI_INTERRUPT_CONTROL 0x63 /* 8 bits */
+#define PCI_CPU_INTERRUPT_PENDING 0x64 /* 32 bits */
+#define PCI_DIAGNOSTIC_1 0x68 /* 16 bits */
+#define PCI_SOFTWARE_INT_CLEAR 0x6a /* 16 bits */
+#define PCI_SOFTWARE_INT_SET 0x6e /* 16 bits */
+#define PCI_SYS_INT_PENDING 0x70 /* 32 bits */
+#define PCI_SYS_INT_PENDING_PIO 0x40000000
+#define PCI_SYS_INT_PENDING_DMA 0x20000000
+#define PCI_SYS_INT_PENDING_PCI 0x10000000
+#define PCI_SYS_INT_PENDING_APSR 0x08000000
+#define PCI_SYS_INT_TARGET_MASK 0x74 /* 32 bits */
+#define PCI_SYS_INT_TARGET_MASK_CLEAR 0x78 /* 32 bits */
+#define PCI_SYS_INT_TARGET_MASK_SET 0x7c /* 32 bits */
+#define PCI_SYS_INT_PENDING_CLEAR 0x83 /* 8 bits */
+#define PCI_SYS_INT_PENDING_CLEAR_ALL 0x80
+#define PCI_SYS_INT_PENDING_CLEAR_PIO 0x40
+#define PCI_SYS_INT_PENDING_CLEAR_DMA 0x20
+#define PCI_SYS_INT_PENDING_CLEAR_PCI 0x10
+#define PCI_IOTLB_CONTROL 0x84 /* 8 bits */
+#define PCI_INT_SELECT_LO 0x88 /* 16 bits */
+#define PCI_ARBITRATION_SELECT 0x8a /* 16 bits */
+#define PCI_INT_SELECT_HI 0x8c /* 16 bits */
+#define PCI_HW_INT_OUTPUT 0x8e /* 16 bits */
+#define PCI_IOTLB_RAM_INPUT 0x90 /* 32 bits */
+#define PCI_IOTLB_CAM_INPUT 0x94 /* 32 bits */
+#define PCI_IOTLB_RAM_OUTPUT 0x98 /* 32 bits */
+#define PCI_IOTLB_CAM_OUTPUT 0x9c /* 32 bits */
+#define PCI_SMBAR0 0xa0 /* 8 bits */
+#define PCI_MSIZE0 0xa1 /* 8 bits */
+#define PCI_PMBAR0 0xa2 /* 8 bits */
+#define PCI_SMBAR1 0xa4 /* 8 bits */
+#define PCI_MSIZE1 0xa5 /* 8 bits */
+#define PCI_PMBAR1 0xa6 /* 8 bits */
+#define PCI_SIBAR 0xa8 /* 8 bits */
+#define PCI_SIBAR_ADDRESS_MASK 0xf
+#define PCI_ISIZE 0xa9 /* 8 bits */
+#define PCI_ISIZE_16M 0xf
+#define PCI_ISIZE_32M 0xe
+#define PCI_ISIZE_64M 0xc
+#define PCI_ISIZE_128M 0x8
+#define PCI_ISIZE_256M 0x0
+#define PCI_PIBAR 0xaa /* 8 bits */
+#define PCI_CPU_COUNTER_LIMIT_HI 0xac /* 32 bits */
+#define PCI_CPU_COUNTER_LIMIT_LO 0xb0 /* 32 bits */
+#define PCI_CPU_COUNTER_LIMIT 0xb4 /* 32 bits */
+#define PCI_SYS_LIMIT 0xb8 /* 32 bits */
+#define PCI_SYS_COUNTER 0xbc /* 32 bits */
+#define PCI_SYS_COUNTER_OVERFLOW (1<<31) /* Limit reached */
+#define PCI_SYS_LIMIT_PSEUDO 0xc0 /* 32 bits */
+#define PCI_USER_TIMER_CONTROL 0xc4 /* 8 bits */
+#define PCI_USER_TIMER_CONFIG 0xc5 /* 8 bits */
+#define PCI_COUNTER_IRQ 0xc6 /* 8 bits */
+#define PCI_COUNTER_IRQ_SET(sys_irq, cpu_irq) ((((sys_irq) & 0xf) << 4) | \
+ ((cpu_irq) & 0xf))
+#define PCI_COUNTER_IRQ_SYS(v) (((v) >> 4) & 0xf)
+#define PCI_COUNTER_IRQ_CPU(v) ((v) & 0xf)
+#define PCI_PIO_ERROR_COMMAND 0xc7 /* 8 bits */
+#define PCI_PIO_ERROR_ADDRESS 0xc8 /* 32 bits */
+#define PCI_IOTLB_ERROR_ADDRESS 0xcc /* 32 bits */
+#define PCI_SYS_STATUS 0xd0 /* 8 bits */
+#define PCI_SYS_STATUS_RESET_ENABLE (1<<0)
+#define PCI_SYS_STATUS_RESET (1<<1)
+#define PCI_SYS_STATUS_WATCHDOG_RESET (1<<4)
+#define PCI_SYS_STATUS_PCI_RESET (1<<5)
+#define PCI_SYS_STATUS_PCI_RESET_ENABLE (1<<6)
+#define PCI_SYS_STATUS_PCI_SATTELITE_MODE (1<<7)
+
+#endif /* !(__SPARC_PCIC_H) */
diff --git a/arch/sparc/include/asm/pcr.h b/arch/sparc/include/asm/pcr.h
new file mode 100644
index 00000000000..cdf800c3326
--- /dev/null
+++ b/arch/sparc/include/asm/pcr.h
@@ -0,0 +1,50 @@
+#ifndef __PCR_H
+#define __PCR_H
+
+struct pcr_ops {
+ u64 (*read_pcr)(unsigned long);
+ void (*write_pcr)(unsigned long, u64);
+ u64 (*read_pic)(unsigned long);
+ void (*write_pic)(unsigned long, u64);
+ u64 (*nmi_picl_value)(unsigned int nmi_hz);
+ u64 pcr_nmi_enable;
+ u64 pcr_nmi_disable;
+};
+extern const struct pcr_ops *pcr_ops;
+
+void deferred_pcr_work_irq(int irq, struct pt_regs *regs);
+void schedule_deferred_pcr_work(void);
+
+#define PCR_PIC_PRIV 0x00000001 /* PIC access is privileged */
+#define PCR_STRACE 0x00000002 /* Trace supervisor events */
+#define PCR_UTRACE 0x00000004 /* Trace user events */
+#define PCR_N2_HTRACE 0x00000008 /* Trace hypervisor events */
+#define PCR_N2_TOE_OV0 0x00000010 /* Trap if PIC 0 overflows */
+#define PCR_N2_TOE_OV1 0x00000020 /* Trap if PIC 1 overflows */
+#define PCR_N2_MASK0 0x00003fc0
+#define PCR_N2_MASK0_SHIFT 6
+#define PCR_N2_SL0 0x0003c000
+#define PCR_N2_SL0_SHIFT 14
+#define PCR_N2_OV0 0x00040000
+#define PCR_N2_MASK1 0x07f80000
+#define PCR_N2_MASK1_SHIFT 19
+#define PCR_N2_SL1 0x78000000
+#define PCR_N2_SL1_SHIFT 27
+#define PCR_N2_OV1 0x80000000
+
+#define PCR_N4_OV 0x00000001 /* PIC overflow */
+#define PCR_N4_TOE 0x00000002 /* Trap On Event */
+#define PCR_N4_UTRACE 0x00000004 /* Trace user events */
+#define PCR_N4_STRACE 0x00000008 /* Trace supervisor events */
+#define PCR_N4_HTRACE 0x00000010 /* Trace hypervisor events */
+#define PCR_N4_MASK 0x000007e0 /* Event mask */
+#define PCR_N4_MASK_SHIFT 5
+#define PCR_N4_SL 0x0000f800 /* Event Select */
+#define PCR_N4_SL_SHIFT 11
+#define PCR_N4_PICNPT 0x00010000 /* PIC non-privileged trap */
+#define PCR_N4_PICNHT 0x00020000 /* PIC non-hypervisor trap */
+#define PCR_N4_NTC 0x00040000 /* Next-To-Commit wrap */
+
+int pcr_arch_init(void);
+
+#endif /* __PCR_H */
diff --git a/arch/sparc/include/asm/percpu.h b/arch/sparc/include/asm/percpu.h
new file mode 100644
index 00000000000..bfb1d19ff1b
--- /dev/null
+++ b/arch/sparc/include/asm/percpu.h
@@ -0,0 +1,8 @@
+#ifndef ___ASM_SPARC_PERCPU_H
+#define ___ASM_SPARC_PERCPU_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/percpu_64.h>
+#else
+#include <asm/percpu_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/percpu_32.h b/arch/sparc/include/asm/percpu_32.h
new file mode 100644