1 /* 2 * s390x SCLP driver 3 * 4 * Copyright (c) 2017 Red Hat Inc 5 * 6 * Authors: 7 * David Hildenbrand <david@redhat.com> 8 * 9 * This code is free software; you can redistribute it and/or modify it 10 * under the terms of the GNU Library General Public License version 2. 11 */ 12 13 #include <libcflat.h> 14 #include <asm/page.h> 15 #include <asm/arch_def.h> 16 #include <asm/interrupt.h> 17 #include <asm/barrier.h> 18 #include <asm/spinlock.h> 19 #include "sclp.h" 20 #include <alloc_phys.h> 21 #include <alloc_page.h> 22 23 extern unsigned long stacktop; 24 25 static uint64_t storage_increment_size; 26 static uint64_t max_ram_size; 27 static uint64_t ram_size; 28 29 char _sccb[PAGE_SIZE] __attribute__((__aligned__(4096))); 30 static volatile bool sclp_busy; 31 static struct spinlock sclp_lock; 32 33 static void mem_init(phys_addr_t mem_end) 34 { 35 phys_addr_t freemem_start = (phys_addr_t)&stacktop; 36 phys_addr_t base, top; 37 38 phys_alloc_init(freemem_start, mem_end - freemem_start); 39 phys_alloc_get_unused(&base, &top); 40 base = (base + PAGE_SIZE - 1) & -PAGE_SIZE; 41 top = top & -PAGE_SIZE; 42 43 /* Make the pages available to the physical allocator */ 44 free_pages((void *)(unsigned long)base, top - base); 45 page_alloc_ops_enable(); 46 } 47 48 void sclp_setup_int(void) 49 { 50 uint64_t mask; 51 52 ctl_set_bit(0, 9); 53 54 mask = extract_psw_mask(); 55 mask |= PSW_MASK_EXT; 56 load_psw_mask(mask); 57 } 58 59 void sclp_handle_ext(void) 60 { 61 ctl_clear_bit(0, 9); 62 spin_lock(&sclp_lock); 63 sclp_busy = false; 64 spin_unlock(&sclp_lock); 65 } 66 67 void sclp_wait_busy(void) 68 { 69 while (sclp_busy) 70 mb(); 71 } 72 73 void sclp_mark_busy(void) 74 { 75 /* 76 * With multiple CPUs we might need to wait for another CPU's 77 * request before grabbing the busy indication. 78 */ 79 while (true) { 80 sclp_wait_busy(); 81 spin_lock(&sclp_lock); 82 if (!sclp_busy) { 83 sclp_busy = true; 84 spin_unlock(&sclp_lock); 85 return; 86 } 87 spin_unlock(&sclp_lock); 88 } 89 } 90 91 static void sclp_read_scp_info(ReadInfo *ri, int length) 92 { 93 unsigned int commands[] = { SCLP_CMDW_READ_SCP_INFO_FORCED, 94 SCLP_CMDW_READ_SCP_INFO }; 95 int i, cc; 96 97 for (i = 0; i < ARRAY_SIZE(commands); i++) { 98 sclp_mark_busy(); 99 memset(&ri->h, 0, sizeof(ri->h)); 100 ri->h.length = length; 101 102 cc = sclp_service_call(commands[i], ri); 103 if (cc) 104 break; 105 if (ri->h.response_code == SCLP_RC_NORMAL_READ_COMPLETION) 106 return; 107 if (ri->h.response_code != SCLP_RC_INVALID_SCLP_COMMAND) 108 break; 109 } 110 report_abort("READ_SCP_INFO failed"); 111 } 112 113 /* Perform service call. Return 0 on success, non-zero otherwise. */ 114 int sclp_service_call(unsigned int command, void *sccb) 115 { 116 int cc; 117 118 sclp_setup_int(); 119 cc = servc(command, __pa(sccb)); 120 sclp_wait_busy(); 121 if (cc == 3) 122 return -1; 123 if (cc == 2) 124 return -1; 125 return 0; 126 } 127 128 void sclp_memory_setup(void) 129 { 130 ReadInfo *ri = (void *)_sccb; 131 uint64_t rnmax, rnsize; 132 int cc; 133 134 sclp_read_scp_info(ri, SCCB_SIZE); 135 136 /* calculate the storage increment size */ 137 rnsize = ri->rnsize; 138 if (!rnsize) { 139 rnsize = ri->rnsize2; 140 } 141 storage_increment_size = rnsize << 20; 142 143 /* calculate the maximum memory size */ 144 rnmax = ri->rnmax; 145 if (!rnmax) { 146 rnmax = ri->rnmax2; 147 } 148 max_ram_size = rnmax * storage_increment_size; 149 150 /* lowcore is always accessible, so the first increment is accessible */ 151 ram_size = storage_increment_size; 152 153 /* probe for r/w memory up to max memory size */ 154 while (ram_size < max_ram_size) { 155 expect_pgm_int(); 156 cc = tprot(ram_size + storage_increment_size - 1); 157 /* stop once we receive an exception or have protected memory */ 158 if (clear_pgm_int() || cc != 0) 159 break; 160 ram_size += storage_increment_size; 161 } 162 163 mem_init(ram_size); 164 } 165 166 uint64_t get_ram_size(void) 167 { 168 return ram_size; 169 } 170 171 uint64_t get_max_ram_size(void) 172 { 173 return max_ram_size; 174 } 175