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

[PATCH] s390: export ipl device parameters

Sysfs interface to export ipl device parameters. Dependent on the ipl type
the interface will look like this:

- ccw ipl:

/sys/firmware/ipl/device
/ipl_type

- fcp ipl:

/sys/firmware/ipl/binary_parameter
/bootprog
/br_lba
/device
/ipl_type
/lun
/scp_data
/wwpn

- otherwise (unknown that is):

/sys/firmware/ipl/ipl_type

Acked-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Heiko Carstens and committed by
Linus Torvalds
1e8e3383 ed3cb6f0

+367 -7
+67 -5
arch/s390/kernel/head.S
··· 485 485 # 486 486 .org 0x10000 487 487 startup:basr %r13,0 # get base 488 - .LPG1: lctl %c0,%c15,.Lctl-.LPG1(%r13) # load control registers 488 + .LPG1: l %r1, .Lget_ipl_device_addr-.LPG1(%r13) 489 + basr %r14, %r1 490 + lctl %c0,%c15,.Lctl-.LPG1(%r13) # load control registers 489 491 la %r12,_pstart-.LPG1(%r13) # pointer to parameter area 490 492 # move IPL device to lowcore 491 493 mvc __LC_IPLDEV(4),IPL_DEVICE-PARMAREA(%r12) ··· 562 560 mr %r2,%r1 # mem size in bytes in %r3 563 561 b .Lfchunk-.LPG1(%r13) 564 562 563 + .align 4 564 + .Lget_ipl_device_addr: 565 + .long .Lget_ipl_device 565 566 .Lpmask: 566 567 .byte 0 567 568 .align 8 ··· 760 755 .global _pend 761 756 _pend: 762 757 758 + .Lget_ipl_device: 759 + basr %r12,0 760 + .LPG2: l %r1,0xb8 # get sid 761 + sll %r1,15 # test if subchannel is enabled 762 + srl %r1,31 763 + ltr %r1,%r1 764 + bz 0(%r14) # subchannel disabled 765 + l %r1,0xb8 766 + la %r5,.Lipl_schib-.LPG2(%r12) 767 + stsch 0(%r5) # get schib of subchannel 768 + bnz 0(%r14) # schib not available 769 + tm 5(%r5),0x01 # devno valid? 770 + bno 0(%r14) 771 + la %r6,ipl_parameter_flags-.LPG2(%r12) 772 + oi 3(%r6),0x01 # set flag 773 + la %r2,ipl_devno-.LPG2(%r12) 774 + mvc 0(2,%r2),6(%r5) # store devno 775 + tm 4(%r5),0x80 # qdio capable device? 776 + bno 0(%r14) 777 + oi 3(%r6),0x02 # set flag 778 + 779 + # copy ipl parameters 780 + 781 + lhi %r0,4096 782 + l %r2,20(%r0) # get address of parameter list 783 + lhi %r3,IPL_PARMBLOCK_ORIGIN 784 + st %r3,20(%r0) 785 + lhi %r4,1 786 + cr %r2,%r3 # start parameters < destination ? 787 + jl 0f 788 + lhi %r1,1 # copy direction is upwards 789 + j 1f 790 + 0: lhi %r1,-1 # copy direction is downwards 791 + ar %r2,%r0 792 + ar %r3,%r0 793 + ar %r2,%r1 794 + ar %r3,%r1 795 + 1: mvc 0(1,%r3),0(%r2) # finally copy ipl parameters 796 + ar %r3,%r1 797 + ar %r2,%r1 798 + sr %r0,%r4 799 + jne 1b 800 + b 0(%r14) 801 + 802 + .align 4 803 + .Lipl_schib: 804 + .rept 13 805 + .long 0 806 + .endr 807 + 808 + .globl ipl_parameter_flags 809 + ipl_parameter_flags: 810 + .long 0 811 + .globl ipl_devno 812 + ipl_devno: 813 + .word 0 814 + 763 815 #ifdef CONFIG_SHARED_KERNEL 764 816 .org 0x100000 765 817 #endif ··· 826 764 # 827 765 .globl _stext 828 766 _stext: basr %r13,0 # get base 829 - .LPG2: 767 + .LPG3: 830 768 # 831 769 # Setup stack 832 770 # 833 - l %r15,.Linittu-.LPG2(%r13) 771 + l %r15,.Linittu-.LPG3(%r13) 834 772 mvc __LC_CURRENT(4),__TI_task(%r15) 835 773 ahi %r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union + THREAD_SIZE 836 774 st %r15,__LC_KERNEL_STACK # set end of kernel stack ··· 844 782 lctl %c0,%c15,0(%r15) 845 783 846 784 # 847 - lam 0,15,.Laregs-.LPG2(%r13) # load access regs needed by uaccess 848 - l %r14,.Lstart-.LPG2(%r13) 785 + lam 0,15,.Laregs-.LPG3(%r13) # load access regs needed by uaccess 786 + l %r14,.Lstart-.LPG3(%r13) 849 787 basr %r14,%r14 # call start_kernel 850 788 # 851 789 # We returned from start_kernel ?!? PANIK
+64 -2
arch/s390/kernel/head64.S
··· 484 484 startup:basr %r13,0 # get base 485 485 .LPG1: sll %r13,1 # remove high order bit 486 486 srl %r13,1 487 + l %r1,.Lget_ipl_device_addr-.LPG1(%r13) 488 + basr %r14,%r1 487 489 lhi %r1,1 # mode 1 = esame 488 490 slr %r0,%r0 # set cpuid to zero 489 491 sigp %r1,%r0,0x12 # switch to esame mode ··· 558 556 mlgr %r2,%r1 # mem size in bytes in %r3 559 557 b .Lfchunk-.LPG1(%r13) 560 558 559 + .align 4 560 + .Lget_ipl_device_addr: 561 + .long .Lget_ipl_device 561 562 .Lpmask: 562 563 .byte 0 563 564 .align 8 ··· 751 746 .global _pend 752 747 _pend: 753 748 749 + .Lget_ipl_device: 750 + basr %r12,0 751 + .LPG2: l %r1,0xb8 # get sid 752 + sll %r1,15 # test if subchannel is enabled 753 + srl %r1,31 754 + ltr %r1,%r1 755 + bz 0(%r14) # subchannel disabled 756 + l %r1,0xb8 757 + la %r5,.Lipl_schib-.LPG2(%r12) 758 + stsch 0(%r5) # get schib of subchannel 759 + bnz 0(%r14) # schib not available 760 + tm 5(%r5),0x01 # devno valid? 761 + bno 0(%r14) 762 + la %r6,ipl_parameter_flags-.LPG2(%r12) 763 + oi 3(%r6),0x01 # set flag 764 + la %r2,ipl_devno-.LPG2(%r12) 765 + mvc 0(2,%r2),6(%r5) # store devno 766 + tm 4(%r5),0x80 # qdio capable device? 767 + bno 0(%r14) 768 + oi 3(%r6),0x02 # set flag 769 + 770 + # copy ipl parameters 771 + 772 + lhi %r0,4096 773 + l %r2,20(%r0) # get address of parameter list 774 + lhi %r3,IPL_PARMBLOCK_ORIGIN 775 + st %r3,20(%r0) 776 + lhi %r4,1 777 + cr %r2,%r3 # start parameters < destination ? 778 + jl 0f 779 + lhi %r1,1 # copy direction is upwards 780 + j 1f 781 + 0: lhi %r1,-1 # copy direction is downwards 782 + ar %r2,%r0 783 + ar %r3,%r0 784 + ar %r2,%r1 785 + ar %r3,%r1 786 + 1: mvc 0(1,%r3),0(%r2) # finally copy ipl parameters 787 + ar %r3,%r1 788 + ar %r2,%r1 789 + sr %r0,%r4 790 + jne 1b 791 + b 0(%r14) 792 + 793 + .align 4 794 + .Lipl_schib: 795 + .rept 13 796 + .long 0 797 + .endr 798 + 799 + .globl ipl_parameter_flags 800 + ipl_parameter_flags: 801 + .long 0 802 + .globl ipl_devno 803 + ipl_devno: 804 + .word 0 805 + 754 806 #ifdef CONFIG_SHARED_KERNEL 755 807 .org 0x100000 756 808 #endif ··· 817 755 # 818 756 .globl _stext 819 757 _stext: basr %r13,0 # get base 820 - .LPG2: 758 + .LPG3: 821 759 # 822 760 # Setup stack 823 761 # ··· 836 774 lctlg %c0,%c15,0(%r15) 837 775 838 776 # 839 - lam 0,15,.Laregs-.LPG2(%r13) # load access regs needed by uaccess 777 + lam 0,15,.Laregs-.LPG3(%r13) # load access regs needed by uaccess 840 778 brasl %r14,start_kernel # go to C code 841 779 # 842 780 # We returned from start_kernel ?!? PANIK
+186
arch/s390/kernel/setup.c
··· 36 36 #include <linux/console.h> 37 37 #include <linux/seq_file.h> 38 38 #include <linux/kernel_stat.h> 39 + #include <linux/device.h> 39 40 40 41 #include <asm/uaccess.h> 41 42 #include <asm/system.h> ··· 686 685 .show = show_cpuinfo, 687 686 }; 688 687 688 + #define DEFINE_IPL_ATTR(_name, _format, _value) \ 689 + static ssize_t ipl_##_name##_show(struct subsystem *subsys, \ 690 + char *page) \ 691 + { \ 692 + return sprintf(page, _format, _value); \ 693 + } \ 694 + static struct subsys_attribute ipl_##_name##_attr = \ 695 + __ATTR(_name, S_IRUGO, ipl_##_name##_show, NULL); 696 + 697 + DEFINE_IPL_ATTR(wwpn, "0x%016llx\n", (unsigned long long) 698 + IPL_PARMBLOCK_START->fcp.wwpn); 699 + DEFINE_IPL_ATTR(lun, "0x%016llx\n", (unsigned long long) 700 + IPL_PARMBLOCK_START->fcp.lun); 701 + DEFINE_IPL_ATTR(bootprog, "%lld\n", (unsigned long long) 702 + IPL_PARMBLOCK_START->fcp.bootprog); 703 + DEFINE_IPL_ATTR(br_lba, "%lld\n", (unsigned long long) 704 + IPL_PARMBLOCK_START->fcp.br_lba); 705 + 706 + enum ipl_type_type { 707 + ipl_type_unknown, 708 + ipl_type_ccw, 709 + ipl_type_fcp, 710 + }; 711 + 712 + static enum ipl_type_type 713 + get_ipl_type(void) 714 + { 715 + struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START; 716 + 717 + if (!IPL_DEVNO_VALID) 718 + return ipl_type_unknown; 719 + if (!IPL_PARMBLOCK_VALID) 720 + return ipl_type_ccw; 721 + if (ipl->hdr.header.version > IPL_MAX_SUPPORTED_VERSION) 722 + return ipl_type_unknown; 723 + if (ipl->fcp.pbt != IPL_TYPE_FCP) 724 + return ipl_type_unknown; 725 + return ipl_type_fcp; 726 + } 727 + 728 + static ssize_t 729 + ipl_type_show(struct subsystem *subsys, char *page) 730 + { 731 + switch (get_ipl_type()) { 732 + case ipl_type_ccw: 733 + return sprintf(page, "ccw\n"); 734 + case ipl_type_fcp: 735 + return sprintf(page, "fcp\n"); 736 + default: 737 + return sprintf(page, "unknown\n"); 738 + } 739 + } 740 + 741 + static struct subsys_attribute ipl_type_attr = __ATTR_RO(ipl_type); 742 + 743 + static ssize_t 744 + ipl_device_show(struct subsystem *subsys, char *page) 745 + { 746 + struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START; 747 + 748 + switch (get_ipl_type()) { 749 + case ipl_type_ccw: 750 + return sprintf(page, "0.0.%04x\n", ipl_devno); 751 + case ipl_type_fcp: 752 + return sprintf(page, "0.0.%04x\n", ipl->fcp.devno); 753 + default: 754 + return 0; 755 + } 756 + } 757 + 758 + static struct subsys_attribute ipl_device_attr = 759 + __ATTR(device, S_IRUGO, ipl_device_show, NULL); 760 + 761 + static struct attribute *ipl_fcp_attrs[] = { 762 + &ipl_type_attr.attr, 763 + &ipl_device_attr.attr, 764 + &ipl_wwpn_attr.attr, 765 + &ipl_lun_attr.attr, 766 + &ipl_bootprog_attr.attr, 767 + &ipl_br_lba_attr.attr, 768 + NULL, 769 + }; 770 + 771 + static struct attribute_group ipl_fcp_attr_group = { 772 + .attrs = ipl_fcp_attrs, 773 + }; 774 + 775 + static struct attribute *ipl_ccw_attrs[] = { 776 + &ipl_type_attr.attr, 777 + &ipl_device_attr.attr, 778 + NULL, 779 + }; 780 + 781 + static struct attribute_group ipl_ccw_attr_group = { 782 + .attrs = ipl_ccw_attrs, 783 + }; 784 + 785 + static struct attribute *ipl_unknown_attrs[] = { 786 + &ipl_type_attr.attr, 787 + NULL, 788 + }; 789 + 790 + static struct attribute_group ipl_unknown_attr_group = { 791 + .attrs = ipl_unknown_attrs, 792 + }; 793 + 794 + static ssize_t 795 + ipl_parameter_read(struct kobject *kobj, char *buf, loff_t off, size_t count) 796 + { 797 + unsigned int size = IPL_PARMBLOCK_SIZE; 798 + 799 + if (off > size) 800 + return 0; 801 + if (off + count > size) 802 + count = size - off; 803 + 804 + memcpy(buf, (void *) IPL_PARMBLOCK_START + off, count); 805 + return count; 806 + } 807 + 808 + static struct bin_attribute ipl_parameter_attr = { 809 + .attr = { 810 + .name = "binary_parameter", 811 + .mode = S_IRUGO, 812 + .owner = THIS_MODULE, 813 + }, 814 + .size = PAGE_SIZE, 815 + .read = &ipl_parameter_read, 816 + }; 817 + 818 + static ssize_t 819 + ipl_scp_data_read(struct kobject *kobj, char *buf, loff_t off, size_t count) 820 + { 821 + unsigned int size = IPL_PARMBLOCK_START->fcp.scp_data_len; 822 + void *scp_data = &IPL_PARMBLOCK_START->fcp.scp_data; 823 + 824 + if (off > size) 825 + return 0; 826 + if (off + count > size) 827 + count = size - off; 828 + 829 + memcpy(buf, scp_data + off, count); 830 + return count; 831 + } 832 + 833 + static struct bin_attribute ipl_scp_data_attr = { 834 + .attr = { 835 + .name = "scp_data", 836 + .mode = S_IRUGO, 837 + .owner = THIS_MODULE, 838 + }, 839 + .size = PAGE_SIZE, 840 + .read = &ipl_scp_data_read, 841 + }; 842 + 843 + static decl_subsys(ipl, NULL, NULL); 844 + 845 + static int __init 846 + ipl_device_sysfs_register(void) { 847 + int rc; 848 + 849 + rc = firmware_register(&ipl_subsys); 850 + if (rc) 851 + return rc; 852 + 853 + switch (get_ipl_type()) { 854 + case ipl_type_ccw: 855 + sysfs_create_group(&ipl_subsys.kset.kobj, &ipl_ccw_attr_group); 856 + break; 857 + case ipl_type_fcp: 858 + sysfs_create_group(&ipl_subsys.kset.kobj, &ipl_fcp_attr_group); 859 + sysfs_create_bin_file(&ipl_subsys.kset.kobj, 860 + &ipl_parameter_attr); 861 + sysfs_create_bin_file(&ipl_subsys.kset.kobj, 862 + &ipl_scp_data_attr); 863 + break; 864 + default: 865 + sysfs_create_group(&ipl_subsys.kset.kobj, 866 + &ipl_unknown_attr_group); 867 + break; 868 + } 869 + return 0; 870 + } 871 + 872 + __initcall(ipl_device_sysfs_register);
+50
include/asm-s390/setup.h
··· 8 8 #ifndef _ASM_S390_SETUP_H 9 9 #define _ASM_S390_SETUP_H 10 10 11 + #include <asm/types.h> 12 + 11 13 #define PARMAREA 0x10400 12 14 #define COMMAND_LINE_SIZE 896 13 15 #define RAMDISK_ORIGIN 0x800000 14 16 #define RAMDISK_SIZE 0x800000 15 17 #define MEMORY_CHUNKS 16 /* max 0x7fff */ 18 + #define IPL_PARMBLOCK_ORIGIN 0x2000 16 19 17 20 #ifndef __ASSEMBLY__ 18 21 ··· 66 63 #define SET_CONSOLE_SCLP do { console_mode = 1; } while (0) 67 64 #define SET_CONSOLE_3215 do { console_mode = 2; } while (0) 68 65 #define SET_CONSOLE_3270 do { console_mode = 3; } while (0) 66 + 67 + struct ipl_list_header { 68 + u32 length; 69 + u8 reserved[3]; 70 + u8 version; 71 + } __attribute__((packed)); 72 + 73 + struct ipl_block_fcp { 74 + u32 length; 75 + u8 pbt; 76 + u8 reserved1[322-1]; 77 + u16 devno; 78 + u8 reserved2[4]; 79 + u64 wwpn; 80 + u64 lun; 81 + u32 bootprog; 82 + u8 reserved3[12]; 83 + u64 br_lba; 84 + u32 scp_data_len; 85 + u8 reserved4[260]; 86 + u8 scp_data[]; 87 + } __attribute__((packed)); 88 + 89 + struct ipl_parameter_block { 90 + union { 91 + u32 length; 92 + struct ipl_list_header header; 93 + } hdr; 94 + struct ipl_block_fcp fcp; 95 + } __attribute__((packed)); 96 + 97 + #define IPL_MAX_SUPPORTED_VERSION (0) 98 + 99 + #define IPL_TYPE_FCP (0) 100 + 101 + /* 102 + * IPL validity flags and parameters as detected in head.S 103 + */ 104 + extern u32 ipl_parameter_flags; 105 + extern u16 ipl_devno; 106 + 107 + #define IPL_DEVNO_VALID (ipl_parameter_flags & 1) 108 + #define IPL_PARMBLOCK_VALID (ipl_parameter_flags & 2) 109 + 110 + #define IPL_PARMBLOCK_START ((struct ipl_parameter_block *) \ 111 + IPL_PARMBLOCK_ORIGIN) 112 + #define IPL_PARMBLOCK_SIZE (IPL_PARMBLOCK_START->hdr.length) 69 113 70 114 #else 71 115