0001
0002
0003
0004
0005
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
0027
0028
0029
0030 void __init setup_replication_mask(void)
0031 {
0032
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
0047 node_set(nasid, ktext_repmask);
0048 }
0049 }
0050 #endif
0051
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
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
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
0101 if (node_isset(client_nasid, ktext_repmask)) {
0102 server_nasid = client_nasid;
0103 copy_kernel(server_nasid);
0104 }
0105
0106
0107 set_ktext_source(client_nasid, server_nasid);
0108 }
0109 }
0110
0111
0112
0113
0114
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 }