Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

s390/sclp: sort out physical vs virtual pointers usage

Provide physical addresses whenever the hardware interface
expects it or a 32-bit value used for tracking.

Variable sclp_early_sccb gets initialized in the decompressor
and points to an address in physcal memory. Yet, it is used
as virtual memory pointer and therefore should be converted.

Note, the other two __bootdata variables sclp_info_sccb and
sclp_info_sccb_valid contain plain data, but no pointers and
do need any special care.

Reviewed-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>

authored by

Alexander Gordeev and committed by
Vasily Gorbik
ada1da31 dd9089b6

+16 -9
+1
arch/s390/include/asm/sclp.h
··· 117 117 118 118 extern char *sclp_early_sccb; 119 119 120 + void sclp_early_adjust_va(void); 120 121 void sclp_early_set_buffer(void *sccb); 121 122 int sclp_early_read_info(void); 122 123 int sclp_early_read_storage_info(void);
+1
arch/s390/kernel/early.c
··· 296 296 297 297 void __init startup_init(void) 298 298 { 299 + sclp_early_adjust_va(); 299 300 reset_tod_clock(); 300 301 check_image_bootable(); 301 302 time_early_init();
+7 -7
drivers/s390/char/sclp.c
··· 163 163 summary.timeout = (u16)req->queue_timeout; 164 164 summary.start_count = (u16)req->start_count; 165 165 166 - sclp_trace(prio, id, (u32)(addr_t)sccb, summary.b, err); 166 + sclp_trace(prio, id, __pa(sccb), summary.b, err); 167 167 } 168 168 169 169 static inline void sclp_trace_register(int prio, char *id, u32 a, u64 b, ··· 502 502 } 503 503 504 504 /* RQAD: Request was added (a=sccb, b=caller) */ 505 - sclp_trace(2, "RQAD", (u32)(addr_t)req->sccb, _RET_IP_, false); 505 + sclp_trace(2, "RQAD", __pa(req->sccb), _RET_IP_, false); 506 506 507 507 req->status = SCLP_REQ_QUEUED; 508 508 req->start_count = 0; ··· 617 617 618 618 list_for_each(l, &sclp_req_queue) { 619 619 req = list_entry(l, struct sclp_req, list); 620 - if (sccb == (u32) (addr_t) req->sccb) 621 - return req; 620 + if (sccb == __pa(req->sccb)) 621 + return req; 622 622 } 623 623 return NULL; 624 624 } 625 625 626 626 static bool ok_response(u32 sccb_int, sclp_cmdw_t cmd) 627 627 { 628 - struct sccb_header *sccb = (struct sccb_header *)(addr_t)sccb_int; 628 + struct sccb_header *sccb = (struct sccb_header *)__va(sccb_int); 629 629 struct evbuf_header *evbuf; 630 630 u16 response; 631 631 ··· 664 664 665 665 /* INT: Interrupt received (a=intparm, b=cmd) */ 666 666 sclp_trace_sccb(0, "INT", param32, active_cmd, active_cmd, 667 - (struct sccb_header *)(addr_t)finished_sccb, 667 + (struct sccb_header *)__va(finished_sccb), 668 668 !ok_response(finished_sccb, active_cmd)); 669 669 670 670 if (finished_sccb) { ··· 1110 1110 /* Is this the interrupt we are waiting for? */ 1111 1111 if (finished_sccb == 0) 1112 1112 return; 1113 - if (finished_sccb != (u32) (addr_t) sclp_init_sccb) 1113 + if (finished_sccb != __pa(sclp_init_sccb)) 1114 1114 panic("sclp: unsolicited interrupt for buffer at 0x%x\n", 1115 1115 finished_sccb); 1116 1116 spin_lock(&sclp_lock);
+1 -1
drivers/s390/char/sclp.h
··· 333 333 "2:\n" 334 334 EX_TABLE(0b, 2b) 335 335 EX_TABLE(1b, 2b) 336 - : "+&d" (cc) : "d" (command), "a" ((unsigned long)sccb) 336 + : "+&d" (cc) : "d" (command), "a" (__pa(sccb)) 337 337 : "cc", "memory"); 338 338 if (cc == 4) 339 339 return -EINVAL;
+5
drivers/s390/char/sclp_early.c
··· 155 155 sclp.has_linemode = 1; 156 156 } 157 157 158 + void __init sclp_early_adjust_va(void) 159 + { 160 + sclp_early_sccb = __va((unsigned long)sclp_early_sccb); 161 + } 162 + 158 163 void __init sclp_early_detect(void) 159 164 { 160 165 void *sccb = sclp_early_sccb;
+1 -1
drivers/s390/char/sclp_sd.c
··· 194 194 struct sclp_sd_evbuf *evbuf; 195 195 int rc; 196 196 197 - sclp_sd_listener_init(&listener, (u32) (addr_t) sccb); 197 + sclp_sd_listener_init(&listener, __pa(sccb)); 198 198 sclp_sd_listener_add(&listener); 199 199 200 200 /* Prepare SCCB */