x86: OLPC: add support for calling into OpenFirmware (v6)
Subsystems (2)
PATCH 1/1 x86: OLPC: add support for calling into OpenFirmware (v6)
Add support for saving OFW's cif, and later calling into it to run OFW commands. OFW remains resident in memory, living within virtual range 0xff800000 - 0xffc00000. A single page directory entry points to the pgdir that OFW actually uses, so rather than saving the entire page table, we grab and install that one entry permanently in the kernel's page table.
This is currently only used by the OLPC XO.
--- Documentation/x86/zero-page.txt | 1 + arch/x86/Kconfig | 9 +++ arch/x86/include/asm/bootparam.h | 11 ++++- arch/x86/include/asm/olpc_ofw.h | 31 +++++++++++ arch/x86/kernel/Makefile | 1 + arch/x86/kernel/head_32.S | 6 ++ arch/x86/kernel/olpc.c | 12 ++--- arch/x86/kernel/olpc_ofw.c | 104 ++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/setup.c | 6 ++ 9 files changed, 173 insertions(+), 8 deletions(-) create mode 100644 arch/x86/include/asm/olpc_ofw.h create mode 100644 arch/x86/kernel/olpc_ofw.c
Documentation/x86/zero-page.txt +1 -0
@@ -18,6 +18,7 @@ Offset Proto Name Meaning 080/010 ALL hd0_info hd0 disk parameter, OBSOLETE!! 090/010 ALL hd1_info hd1 disk parameter, OBSOLETE!! 0A0/010 ALL sys_desc_table System description table (struct sys_desc_table) +0B0/010 ALL olpc_ofw_header OLPC's OpenFirmware CIF and friends 140/080 ALL edid_info Video mode setup (struct edid_info) 1C0/020 ALL efi_info EFI 32 information (struct efi_info) 1E0/004 ALL alk_mem_k Alternative mem check, in KB
arch/x86/Kconfig +9 -0
@@ -2062,6 +2062,15 @@ config OLPC Add support for detecting the unique features of the OLPC XO hardware. +config OLPC_OPENFIRMWARE + bool "Support for OLPC's Open Firmware" + depends on !X86_64 && !X86_PAE + default y if OLPC + help + This option adds support for the implementation of Open Firmware + that is used on the OLPC XO-1 Children's Machine. + If unsure, say N here. + endif # X86_32 config K8_NB
arch/x86/include/asm/bootparam.h +10 -1
@@ -70,6 +70,14 @@ struct sys_desc_table {__u8 table[14 ]; }; +/* Gleaned from OFW's set-parameters in cpu/x86/pc/linux.fth */ +struct olpc_ofw_header { +__u32 ofw_magic;/* OFW signature */ +__u32 ofw_version; +__u32 cif_handler;/* callback into OFW */ +__u32 irq_desc_table; +} __attribute__((packed)); +struct efi_info {__u32 efi_loader_signature;__u32 efi_systab;
@@ -92,7 +100,8 @@ struct boot_params {__u8 hd0_info[16 ];/* obsolete! */ /* 0x080 */ __u8 hd1_info[16 ];/* obsolete! */ /* 0x090 */ struct sys_desc_table sys_desc_table;/* 0x0a0 */ -__u8 _pad4[144 ];/* 0x0b0 */ +struct olpc_ofw_header olpc_ofw_header;/* 0x0b0 */ +__u8 _pad4[128 ];/* 0x0c0 */ struct edid_info edid_info;/* 0x140 */ struct efi_info efi_info;/* 0x1c0 */ __u32 alt_mem_k;/* 0x1e0 */
arch/x86/include/asm/olpc_ofw.h new file +31 -0
@@ -0,0 +1,31 @@ +#ifndef _ASM_X86_OLPC_OFW_H +#define _ASM_X86_OLPC_OFW_H + +/* index into the page table containing the entry OFW occupies */ +#define OLPC_OFW_PDE_NR 1022 + +#define OLPC_OFW_SIG 0x2057464F/* aka "OFW " */ + +#ifdef CONFIG_OLPC_OPENFIRMWARE + +/* run an OFW command by calling into the firmware */ +#define olpc_ofw (name, args, res) \ + __olpc_ofw((name), ARRAY_SIZE(args), args, ARRAY_SIZE(res), res) + +extern int __olpc_ofw (const char *name,int nr_args,void **args,int nr_res, +void **res); + +/* determine whether OFW is available and lives in the proper memory */ +extern void olpc_ofw_detect (void ); + +/* install OFW's pde permanently into the kernel's pgtable */ +extern void setup_olpc_ofw_pgd (void ); + +#else /* !CONFIG_OLPC_OPENFIRMWARE */ + +static inline void olpc_ofw_detect (void ) { } +static inline void setup_olpc_ofw_pgd (void ) { } + +#endif /* !CONFIG_OLPC_OPENFIRMWARE */ + +#endif /* _ASM_X86_OLPC_OFW_H */
arch/x86/kernel/Makefile +1 -0
@@ -104,6 +104,7 @@ obj-$(CONFIG_SCx200) += scx200.o scx200-y += scx200_32.o obj-$(CONFIG_OLPC) += olpc.o +obj-$(CONFIG_OLPC_OPENFIRMWARE) += olpc_ofw.o obj-$(CONFIG_X86_MRST) += mrst.o microcode-y := microcode_core.o
arch/x86/kernel/head_32.S +6 -0
@@ -131,6 +131,12 @@ ENTRY(startup_32) movsl 1: +#ifdef CONFIG_OLPC_OPENFIRMWARE + /* save OFW's pgdir table for later use when calling into OFW */ + movl %cr3, %eax + movl %eax, pa(olpc_ofw_pgd) +#endif + #ifdef CONFIG_PARAVIRT /* This is can only trip for a broken bootloader... */ cmpw $0x207, pa(boot_params + BP_version)
arch/x86/kernel/olpc.c +5 -7
@@ -21,10 +21,7 @@#include <asm/geode.h> #include <asm/setup.h> #include <asm/olpc.h> - -#ifdef CONFIG_OPEN_FIRMWARE -#include <asm/ofw.h> -#endif +#include <asm/olpc_ofw.h> struct olpc_platform_t olpc_platform_info;EXPORT_SYMBOL_GPL (olpc_platform_info);
@@ -188,14 +185,15 @@ err: }EXPORT_SYMBOL_GPL (olpc_ec_cmd); -#ifdef CONFIG_OPEN_FIRMWARE +#ifdef CONFIG_OLPC_OPENFIRMWARE static void __init platform_detect (void ) {size_t propsize;__be32 rev; +void *args[] = {NULL ,"board-revision-int" , &rev, (void *)4 }; +void *res[] = { &propsize }; -if (ofw ("getprop" ,4 ,1 ,NULL ,"board-revision-int" , &rev,4 , - &propsize) || propsize !=4 ) { +if (olpc_ofw ("getprop" , args, res) || propsize !=4 ) {printk (KERN_ERR "ofw: getprop call failed!\n" ); rev =cpu_to_be32 (0 ); }
arch/x86/kernel/olpc_ofw.c new file +104 -0
104 lines not on this page · raw message
arch/x86/kernel/setup.c +6 -0
@@ -102,6 +102,7 @@#include <asm/paravirt.h> #include <asm/hypervisor.h> +#include <asm/olpc_ofw.h> #include <asm/percpu.h> #include <asm/topology.h>
@@ -736,10 +737,15 @@ void __init setup_arch(char **cmdline_p)/* VMI may relocate the fixmap; do this before touching ioremap area */ vmi_init (); +/* OFW also may relocate the fixmap */ +olpc_ofw_detect (); +early_trap_init ();early_cpu_init ();early_ioremap_init (); +setup_olpc_ofw_pgd (); +ROOT_DEV =old_decode_dev (boot_params.hdr.root_dev); screen_info = boot_params.screen_info; edid_info = boot_params.edid_info;
Signature · 1 line
1.5.6.5
[tip:x86/olpc] x86, olpc: Add support for calling into OpenFirmware
Commit-ID: fd699c76552bbfa66631f019be415a87dbb08237 Gitweb: http://git.kernel.org/tip/fd699c76552bbfa66631f019be415a87dbb08237 Author: Andres Salomon <[email protected]> AuthorDate: Fri, 18 Jun 2010 17:46:53 -0400 Committer: H. Peter Anvin <[email protected]> CommitDate: Fri, 18 Jun 2010 14:54:36 -0700
x86, olpc: Add support for calling into OpenFirmware
Add support for saving OFW's cif, and later calling into it to run OFW commands. OFW remains resident in memory, living within virtual range 0xff800000 - 0xffc00000. A single page directory entry points to the pgdir that OFW actually uses, so rather than saving the entire page table, we grab and install that one entry permanently in the kernel's page table.
This is currently only used by the OLPC XO. Note that this particular calling convention breaks PAE and PAT, and so cannot be used on newer x86 hardware.
LKML-Reference: <[email protected]>
--- Documentation/x86/zero-page.txt | 1 + arch/x86/Kconfig | 9 +++ arch/x86/include/asm/bootparam.h | 11 ++++- arch/x86/include/asm/olpc_ofw.h | 31 +++++++++++ arch/x86/kernel/Makefile | 1 + arch/x86/kernel/head_32.S | 6 ++ arch/x86/kernel/olpc.c | 12 ++--- arch/x86/kernel/olpc_ofw.c | 104 ++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/setup.c | 6 ++ 9 files changed, 173 insertions(+), 8 deletions(-)
Documentation/x86/zero-page.txt +1 -0
@@ -18,6 +18,7 @@ Offset Proto Name Meaning 080/010 ALL hd0_info hd0 disk parameter, OBSOLETE!! 090/010 ALL hd1_info hd1 disk parameter, OBSOLETE!! 0A0/010 ALL sys_desc_table System description table (struct sys_desc_table) +0B0/010 ALL olpc_ofw_header OLPC's OpenFirmware CIF and friends 140/080 ALL edid_info Video mode setup (struct edid_info) 1C0/020 ALL efi_info EFI 32 information (struct efi_info) 1E0/004 ALL alk_mem_k Alternative mem check, in KB
arch/x86/Kconfig +9 -0
@@ -2062,6 +2062,15 @@ config OLPC Add support for detecting the unique features of the OLPC XO hardware. +config OLPC_OPENFIRMWARE + bool "Support for OLPC's Open Firmware" + depends on !X86_64 && !X86_PAE + default y if OLPC + help + This option adds support for the implementation of Open Firmware + that is used on the OLPC XO-1 Children's Machine. + If unsure, say N here. + endif # X86_32 config K8_NB
arch/x86/include/asm/bootparam.h +10 -1
@@ -70,6 +70,14 @@ struct sys_desc_table {__u8 table[14 ]; }; +/* Gleaned from OFW's set-parameters in cpu/x86/pc/linux.fth */ +struct olpc_ofw_header { +__u32 ofw_magic;/* OFW signature */ +__u32 ofw_version; +__u32 cif_handler;/* callback into OFW */ +__u32 irq_desc_table; +} __attribute__((packed)); +struct efi_info {__u32 efi_loader_signature;__u32 efi_systab;
@@ -92,7 +100,8 @@ struct boot_params {__u8 hd0_info[16 ];/* obsolete! */ /* 0x080 */ __u8 hd1_info[16 ];/* obsolete! */ /* 0x090 */ struct sys_desc_table sys_desc_table;/* 0x0a0 */ -__u8 _pad4[144 ];/* 0x0b0 */ +struct olpc_ofw_header olpc_ofw_header;/* 0x0b0 */ +__u8 _pad4[128 ];/* 0x0c0 */ struct edid_info edid_info;/* 0x140 */ struct efi_info efi_info;/* 0x1c0 */ __u32 alt_mem_k;/* 0x1e0 */
arch/x86/include/asm/olpc_ofw.h new file +31 -0
@@ -0,0 +1,31 @@ +#ifndef _ASM_X86_OLPC_OFW_H +#define _ASM_X86_OLPC_OFW_H + +/* index into the page table containing the entry OFW occupies */ +#define OLPC_OFW_PDE_NR 1022 + +#define OLPC_OFW_SIG 0x2057464F/* aka "OFW " */ + +#ifdef CONFIG_OLPC_OPENFIRMWARE + +/* run an OFW command by calling into the firmware */ +#define olpc_ofw (name, args, res) \ + __olpc_ofw((name), ARRAY_SIZE(args), args, ARRAY_SIZE(res), res) + +extern int __olpc_ofw (const char *name,int nr_args,void **args,int nr_res, +void **res); + +/* determine whether OFW is available and lives in the proper memory */ +extern void olpc_ofw_detect (void ); + +/* install OFW's pde permanently into the kernel's pgtable */ +extern void setup_olpc_ofw_pgd (void ); + +#else /* !CONFIG_OLPC_OPENFIRMWARE */ + +static inline void olpc_ofw_detect (void ) { } +static inline void setup_olpc_ofw_pgd (void ) { } + +#endif /* !CONFIG_OLPC_OPENFIRMWARE */ + +#endif /* _ASM_X86_OLPC_OFW_H */
arch/x86/kernel/Makefile +1 -0
@@ -104,6 +104,7 @@ obj-$(CONFIG_SCx200) += scx200.o scx200-y += scx200_32.o obj-$(CONFIG_OLPC) += olpc.o +obj-$(CONFIG_OLPC_OPENFIRMWARE) += olpc_ofw.o obj-$(CONFIG_X86_MRST) += mrst.o microcode-y := microcode_core.o
arch/x86/kernel/head_32.S +6 -0
@@ -131,6 +131,12 @@ ENTRY(startup_32) movsl 1: +#ifdef CONFIG_OLPC_OPENFIRMWARE + /* save OFW's pgdir table for later use when calling into OFW */ + movl %cr3, %eax + movl %eax, pa(olpc_ofw_pgd) +#endif + #ifdef CONFIG_PARAVIRT /* This is can only trip for a broken bootloader... */ cmpw $0x207, pa(boot_params + BP_version)
arch/x86/kernel/olpc.c +5 -7
@@ -21,10 +21,7 @@#include <asm/geode.h> #include <asm/setup.h> #include <asm/olpc.h> - -#ifdef CONFIG_OPEN_FIRMWARE -#include <asm/ofw.h> -#endif +#include <asm/olpc_ofw.h> struct olpc_platform_t olpc_platform_info;EXPORT_SYMBOL_GPL (olpc_platform_info);
@@ -188,14 +185,15 @@ err: }EXPORT_SYMBOL_GPL (olpc_ec_cmd); -#ifdef CONFIG_OPEN_FIRMWARE +#ifdef CONFIG_OLPC_OPENFIRMWARE static void __init platform_detect (void ) {size_t propsize;__be32 rev; +void *args[] = {NULL ,"board-revision-int" , &rev, (void *)4 }; +void *res[] = { &propsize }; -if (ofw ("getprop" ,4 ,1 ,NULL ,"board-revision-int" , &rev,4 , - &propsize) || propsize !=4 ) { +if (olpc_ofw ("getprop" , args, res) || propsize !=4 ) {printk (KERN_ERR "ofw: getprop call failed!\n" ); rev =cpu_to_be32 (0 ); }
arch/x86/kernel/olpc_ofw.c new file +104 -0
104 lines not on this page · raw message
arch/x86/kernel/setup.c +6 -0
@@ -102,6 +102,7 @@#include <asm/paravirt.h> #include <asm/hypervisor.h> +#include <asm/olpc_ofw.h> #include <asm/percpu.h> #include <asm/topology.h>
@@ -736,10 +737,15 @@ void __init setup_arch(char **cmdline_p)/* VMI may relocate the fixmap; do this before touching ioremap area */ vmi_init (); +/* OFW also may relocate the fixmap */ +olpc_ofw_detect (); +early_trap_init ();early_cpu_init ();early_ioremap_init (); +setup_olpc_ofw_pgd (); +ROOT_DEV =old_decode_dev (boot_params.hdr.root_dev); screen_info = boot_params.screen_info; edid_info = boot_params.edid_info;
[tip:x86/olpc] x86, olpc: Add comment about implicit optimization barrier
In reply to Andres SalomonCommit-ID: 75a9cac430a1bd2a5219c74508ca01b0ddfddc9a Gitweb: http://git.kernel.org/tip/75a9cac430a1bd2a5219c74508ca01b0ddfddc9a Author: Andres Salomon <[email protected]> AuthorDate: Wed, 23 Jun 2010 20:27:00 -0400 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 24 Jun 2010 11:40:47 +0200
x86, olpc: Add comment about implicit optimization barrier
LKML-Reference: <[email protected]>
--- arch/x86/kernel/olpc_ofw.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
arch/x86/kernel/olpc_ofw.c +2 -0
@@ -35,6 +35,8 @@ void __init setup_olpc_ofw_pgd(void)/* install OFW's PDE permanently into the kernel's pgtable */ set_pgd (&swapper_pg_dir[OLPC_OFW_PDE_NR ], *ofw_pde); +/* implicit optimization barrier here due to uninline function return */ +early_iounmap (base,sizeof (olpc_ofw_pgd) *PTRS_PER_PGD ); }