Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Ported from IRIX to Linux by Kanoj Sarcar, 06/08/00.
0004  * Copyright 2000 - 2001 Silicon Graphics, Inc.
0005  * Copyright 2000 - 2001 Kanoj Sarcar (kanoj@sgi.com)
0006  */
0007 #include <linux/init.h>
0008 #include <linux/mm.h>
0009 #include <linux/mmzone.h>
0010 #include <linux/kernel.h>
0011 #include <linux/nodemask.h>
0012 #include <linux/string.h>
0013 
0014 #include <asm/page.h>
0015 #include <asm/sections.h>
0016 #include <asm/sn/types.h>
0017 #include <asm/sn/arch.h>
0018 #include <asm/sn/gda.h>
0019 #include <asm/sn/mapped_kernel.h>
0020 
0021 #include "ip27-common.h"
0022 
0023 static nodemask_t ktext_repmask;
0024 
0025 /*
0026  * XXX - This needs to be much smarter about where it puts copies of the
0027  * kernel.  For example, we should never put a copy on a headless node,
0028  * and we should respect the topology of the machine.
0029  */
0030 void __init setup_replication_mask(void)
0031 {
0032     /* Set only the master cnode's bit.  The master cnode is always 0. */
0033     nodes_clear(ktext_repmask);
0034     node_set(0, ktext_repmask);
0035 
0036 #ifdef CONFIG_REPLICATE_KTEXT
0037 #ifndef CONFIG_MAPPED_KERNEL
0038 #error Kernel replication works with mapped kernel support. No calias support.
0039 #endif
0040     {
0041         nasid_t nasid;
0042 
0043         for_each_online_node(nasid) {
0044             if (nasid == 0)
0045                 continue;
0046             /* Advertise that we have a copy of the kernel */
0047             node_set(nasid, ktext_repmask);
0048         }
0049     }
0050 #endif
0051     /* Set up a GDA pointer to the replication mask. */
0052     GDA->g_ktext_repmask = &ktext_repmask;
0053 }
0054 
0055 
0056 static __init void set_ktext_source(nasid_t client_nasid, nasid_t server_nasid)
0057 {
0058     kern_vars_t *kvp;
0059 
0060     kvp = &hub_data(client_nasid)->kern_vars;
0061 
0062     KERN_VARS_ADDR(client_nasid) = (unsigned long)kvp;
0063 
0064     kvp->kv_magic = KV_MAGIC;
0065     kvp->kv_ro_nasid = server_nasid;
0066     kvp->kv_rw_nasid = master_nasid;
0067     kvp->kv_ro_baseaddr = NODE_CAC_BASE(server_nasid);
0068     kvp->kv_rw_baseaddr = NODE_CAC_BASE(master_nasid);
0069     printk("REPLICATION: ON nasid %d, ktext from nasid %d, kdata from nasid %d\n", client_nasid, server_nasid, master_nasid);
0070 }
0071 
0072 /* XXX - When the BTE works, we should use it instead of this. */
0073 static __init void copy_kernel(nasid_t dest_nasid)
0074 {
0075     unsigned long dest_kern_start, source_start, source_end, kern_size;
0076 
0077     source_start = (unsigned long) _stext;
0078     source_end = (unsigned long) _etext;
0079     kern_size = source_end - source_start;
0080 
0081     dest_kern_start = CHANGE_ADDR_NASID(MAPPED_KERN_RO_TO_K0(source_start),
0082                         dest_nasid);
0083     memcpy((void *)dest_kern_start, (void *)source_start, kern_size);
0084 }
0085 
0086 void __init replicate_kernel_text(void)
0087 {
0088     nasid_t client_nasid;
0089     nasid_t server_nasid;
0090 
0091     server_nasid = master_nasid;
0092 
0093     /* Record where the master node should get its kernel text */
0094     set_ktext_source(master_nasid, master_nasid);
0095 
0096     for_each_online_node(client_nasid) {
0097         if (client_nasid == 0)
0098             continue;
0099 
0100         /* Check if this node should get a copy of the kernel */
0101         if (node_isset(client_nasid, ktext_repmask)) {
0102             server_nasid = client_nasid;
0103             copy_kernel(server_nasid);
0104         }
0105 
0106         /* Record where this node should get its kernel text */
0107         set_ktext_source(client_nasid, server_nasid);
0108     }
0109 }
0110 
0111 /*
0112  * Return pfn of first free page of memory on a node. PROM may allocate
0113  * data structures on the first couple of pages of the first slot of each
0114  * node. If this is the case, getfirstfree(node) > getslotstart(node, 0).
0115  */
0116 unsigned long node_getfirstfree(nasid_t nasid)
0117 {
0118     unsigned long loadbase = REP_BASE;
0119     unsigned long offset;
0120 
0121 #ifdef CONFIG_MAPPED_KERNEL
0122     loadbase += 16777216;
0123 #endif
0124     offset = PAGE_ALIGN((unsigned long)(&_end)) - loadbase;
0125     if ((nasid == 0) || (node_isset(nasid, ktext_repmask)))
0126         return TO_NODE(nasid, offset) >> PAGE_SHIFT;
0127     else
0128         return KDM_TO_PHYS(PAGE_ALIGN(SYMMON_STK_ADDR(nasid, 0))) >> PAGE_SHIFT;
0129 }