* [PATCH] MIPS: Add option for running kernel in mapped address space.
@ 2009-01-08 1:41 David Daney
2009-01-09 1:26 ` David VomLehn
0 siblings, 1 reply; 3+ messages in thread
From: David Daney @ 2009-01-08 1:41 UTC (permalink / raw)
To: linux-mips; +Cc: David Daney
This is a preliminary patch to allow the kernel to run in mapped
address space via a wired TLB entry. Probably in a future version I
would factor out the OCTEON specific parts to a separate patch.
Each supported processor would probably need to doctor up its
kernel-entry-init.h in a similar manner.
Signed-off-by: David Daney <ddaney@caviumnetworks.com>
---
arch/mips/Kconfig | 17 +++++++
arch/mips/Makefile | 10 ++++-
.../asm/mach-cavium-octeon/kernel-entry-init.h | 50 ++++++++++++++++++++
arch/mips/include/asm/page.h | 10 ++++-
arch/mips/include/asm/pgtable-64.h | 7 ++-
arch/mips/kernel/traps.c | 23 +++++++--
arch/mips/kernel/vmlinux.lds.S | 11 ++++-
arch/mips/mm/page.c | 6 ++
arch/mips/mm/tlb-r4k.c | 4 ++
9 files changed, 129 insertions(+), 9 deletions(-)
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 780b520..d9c46a4 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1431,6 +1431,23 @@ config PAGE_SIZE_64KB
endchoice
+config MAPPED_KERNEL
+ bool "Mapped kernel"
+ help
+ Select this option if you want the kernel's code and data to
+ be in mapped memory. The kernel will be mapped using a
+ single wired TLB entry, thus reducing the number of
+ available TLB entries by one. Kernel modules will be able
+ to use a more efficient calling convention.
+
+config PHYS_LOAD_ADDRESS
+ hex "Physical load address"
+ depends on MAPPED_KERNEL
+ default ffffffff81400000
+ help
+ The physical load address reflected as the program header
+ physical address in the kernel ELF image.
+
config BOARD_SCACHE
bool
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 0bc2120..5468f6d 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -82,7 +82,10 @@ all-$(CONFIG_BOOT_ELF64) := $(vmlinux-64)
cflags-y += -G 0 -mno-abicalls -fno-pic -pipe
cflags-y += -msoft-float
LDFLAGS_vmlinux += -G 0 -static -n -nostdlib
+
+ifndef CONFIG_MAPPED_KERNEL
MODFLAGS += -mlong-calls
+endif
cflags-y += -ffreestanding
@@ -605,6 +608,11 @@ endif
cflags-y += -I$(srctree)/arch/mips/include/asm/mach-generic
drivers-$(CONFIG_PCI) += arch/mips/pci/
+ifdef CONFIG_MAPPED_KERNEL
+ PHYS_LOAD_ADDRESS = -D"PHYSADDR=0x$(CONFIG_PHYS_LOAD_ADDRESS)"
+ load-y = 0xffffffffc0000000
+endif
+
ifdef CONFIG_32BIT
ifdef CONFIG_CPU_LITTLE_ENDIAN
JIFFIES = jiffies_64
@@ -662,7 +670,7 @@ OBJCOPYFLAGS += --remove-section=.reginfo
CPPFLAGS_vmlinux.lds := \
$(KBUILD_CFLAGS) \
- -D"LOADADDR=$(load-y)" \
+ -D"LOADADDR=$(load-y)" $(PHYS_LOAD_ADDRESS) \
-D"JIFFIES=$(JIFFIES)" \
-D"DATAOFFSET=$(if $(dataoffset-y),$(dataoffset-y),0)"
diff --git a/arch/mips/include/asm/mach-cavium-octeon/kernel-entry-init.h b/arch/mips/include/asm/mach-cavium-octeon/kernel-entry-init.h
index 0b2b5eb..bf36d82 100644
--- a/arch/mips/include/asm/mach-cavium-octeon/kernel-entry-init.h
+++ b/arch/mips/include/asm/mach-cavium-octeon/kernel-entry-init.h
@@ -27,6 +27,56 @@
# a3 = address of boot descriptor block
.set push
.set arch=octeon
+#ifdef CONFIG_MAPPED_KERNEL
+ # Set up the TLB index 0 for wired access to kernel.
+ # Assume we were loaded with sufficient alignment so that we
+ # can cover the image with two pages.
+ dla v0, _end
+ dla v1, _text
+ dsubu v0, v0, v1 # size of image
+ move v1, zero
+ li t1, -1 # shift count.
+1: dsrl v0, v0, 1 # mask into v1
+ dsll v1, v1, 1
+ daddiu t1, t1, 1
+ ori v1, v1, 1
+ bne v0, zero, 1b
+ daddiu t2, t1, -6
+ mtc0 v1, $5, 0 # PageMask
+ dla t3, 0xffffffffc0000000 # kernel address
+ dmtc0 t3, $10, 0 # EntryHi
+ bal 1f
+1: dla v0, 0x7fffffff
+ and ra, ra, v0 # physical address of pc in ra
+ dsrl v1, v1, 1
+ nor v1, v1, zero
+ and ra, ra, v1
+ dsubu v1, t3, ra # virtual to physical offset into v1
+ dsrlv v0, ra, t1
+ dsllv v0, v0, t2
+ ori v0, v0, 0x1f
+ dmtc0 v0, $2, 0 # EntryLo1
+ dsrlv v0, ra, t1
+ daddiu v0, v0, 1
+ dsllv v0, v0, t2
+ ori v0, v0, 0x1f
+ dmtc0 v0, $3, 0 # EntryLo2
+ mtc0 $0, $0, 0 # Set index to zero
+ tlbwi
+ li v0, 1
+ mtc0 v0, $6, 0 # Wired
+ dla v0, phys_to_kernel_offset
+ sd v1, 0(v0)
+ dla v0, kernel_image_end
+ li v1, 2
+ dsllv v1, v1, t1
+ daddu v1, v1, t3
+ sd v1, 0(v0)
+ dla v0, continue_in_mapped_space
+ jr v0
+
+continue_in_mapped_space:
+#endif
# Read the cavium mem control register
dmfc0 v0, CP0_CVMMEMCTL_REG
# Clear the lower 6 bits, the CVMSEG size
diff --git a/arch/mips/include/asm/page.h b/arch/mips/include/asm/page.h
index fe7a88e..5a20413 100644
--- a/arch/mips/include/asm/page.h
+++ b/arch/mips/include/asm/page.h
@@ -151,7 +151,15 @@ typedef struct { unsigned long pgprot; } pgprot_t;
((unsigned long)(x) - PAGE_OFFSET + PHYS_OFFSET)
#endif
#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET - PHYS_OFFSET))
-#define __pa_symbol(x) __pa(RELOC_HIDE((unsigned long)(x), 0))
+
+#ifndef __ASSEMBLY__
+# ifdef CONFIG_MAPPED_KERNEL
+extern unsigned long phys_to_kernel_offset;
+# define __pa_symbol(x) (RELOC_HIDE((unsigned long)(x), 0) - phys_to_kernel_offset)
+# else
+# define __pa_symbol(x) __pa(RELOC_HIDE((unsigned long)(x), 0))
+# endif
+#endif
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
diff --git a/arch/mips/include/asm/pgtable-64.h b/arch/mips/include/asm/pgtable-64.h
index 943515f..1905a43 100644
--- a/arch/mips/include/asm/pgtable-64.h
+++ b/arch/mips/include/asm/pgtable-64.h
@@ -107,7 +107,12 @@
#if defined(CONFIG_MODULES) && defined(KBUILD_64BIT_SYM32) && \
VMALLOC_START != CKSSEG
/* Load modules into 32bit-compatible segment. */
-#define MODULE_START CKSSEG
+#ifdef CONFIG_MAPPED_KERNEL
+extern unsigned long kernel_image_end;
+#define MODULE_START kernel_image_end
+#else
+#define MODULE_START CKSSEG
+#endif
#define MODULE_END (FIXADDR_START-2*PAGE_SIZE)
extern pgd_t module_pg_dir[PTRS_PER_PGD];
#endif
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 1055348..b44bcf8 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -49,6 +49,8 @@
#include <asm/stacktrace.h>
#include <asm/irq.h>
+#include "../mm/uasm.h"
+
extern void check_wait(void);
extern asmlinkage void r4k_wait(void);
extern asmlinkage void rollback_handle_int(void);
@@ -1295,9 +1297,18 @@ void *set_except_vector(int n, void *addr)
exception_handlers[n] = handler;
if (n == 0 && cpu_has_divec) {
- *(u32 *)(ebase + 0x200) = 0x08000000 |
- (0x03ffffff & (handler >> 2));
- local_flush_icache_range(ebase + 0x200, ebase + 0x204);
+ unsigned long jump_mask = ~((1 << 28) - 1);
+ u32 *buf = (u32 *)(ebase + 0x200);
+ unsigned int k0 = 26;
+ if((handler & jump_mask) == ((ebase + 0x200) & jump_mask)) {
+ uasm_i_j(&buf, handler & jump_mask);
+ uasm_i_nop(&buf);
+ } else {
+ UASM_i_LA(&buf, k0, handler);
+ uasm_i_jr(&buf, k0);
+ uasm_i_nop(&buf);
+ }
+ local_flush_icache_range(ebase + 0x200, (unsigned long)buf);
}
return (void *)old_handler;
}
@@ -1570,6 +1581,8 @@ void __cpuinit per_cpu_trap_init(void)
evpe(vpflags);
} else
set_c0_cause(CAUSEF_IV);
+ } else {
+ clear_c0_cause(CAUSEF_IV);
}
/*
@@ -1670,9 +1683,9 @@ void __init trap_init(void)
return; /* Already done */
#endif
- if (cpu_has_veic || cpu_has_vint)
+ if (cpu_has_veic || cpu_has_vint) {
ebase = (unsigned long) alloc_bootmem_low_pages(0x200 + VECTORSPACING*64);
- else {
+ } else {
ebase = CAC_BASE;
if (cpu_has_mips_r2)
ebase += (read_c0_ebase() & 0x3ffff000);
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index 58738c8..f96c332 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -4,11 +4,20 @@
#undef mips
#define mips mips
OUTPUT_ARCH(mips)
+#ifdef PHYSADDR
+ENTRY(phys_entry)
+#define AT_LOCATION AT(PHYSADDR)
+#else
ENTRY(kernel_entry)
+#define AT_LOCATION
+#endif
PHDRS {
- text PT_LOAD FLAGS(7); /* RWX */
+ text PT_LOAD AT_LOCATION FLAGS(7); /* RWX */
note PT_NOTE FLAGS(4); /* R__ */
}
+#ifdef PHYSADDR
+phys_entry = kernel_entry - LOADADDR + PHYSADDR;
+#endif
jiffies = JIFFIES;
SECTIONS
diff --git a/arch/mips/mm/page.c b/arch/mips/mm/page.c
index 1417c64..0070aa0 100644
--- a/arch/mips/mm/page.c
+++ b/arch/mips/mm/page.c
@@ -687,3 +687,9 @@ void copy_page(void *to, void *from)
}
#endif /* CONFIG_SIBYTE_DMA_PAGEOPS */
+
+#ifdef CONFIG_MAPPED_KERNEL
+/* Initialized so it is not clobbered when .bss is zeroed. */
+unsigned long phys_to_kernel_offset = 1;
+unsigned long kernel_image_end = 1;
+#endif
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
index 5ce2fa7..ebe4ee8 100644
--- a/arch/mips/mm/tlb-r4k.c
+++ b/arch/mips/mm/tlb-r4k.c
@@ -477,8 +477,12 @@ void __cpuinit tlb_init(void)
*/
probe_tlb(config);
write_c0_pagemask(PM_DEFAULT_MASK);
+#ifndef CONFIG_MAPPED_KERNEL
write_c0_wired(0);
+#endif
+#ifndef CONFIG_CPU_CAVIUM_OCTEON
write_c0_framemask(0);
+#endif
temp_tlb_entry = current_cpu_data.tlbsize - 1;
/* From this point on the ARC firmware is dead. */
--
1.5.6.6
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] MIPS: Add option for running kernel in mapped address space.
2009-01-08 1:41 [PATCH] MIPS: Add option for running kernel in mapped address space David Daney
@ 2009-01-09 1:26 ` David VomLehn
2009-01-09 2:33 ` David Daney
0 siblings, 1 reply; 3+ messages in thread
From: David VomLehn @ 2009-01-09 1:26 UTC (permalink / raw)
To: David Daney; +Cc: linux-mips
On Wed, 2009-01-07 at 17:41 -0800, David Daney wrote:
> This is a preliminary patch to allow the kernel to run in mapped
> address space via a wired TLB entry. Probably in a future version I
> would factor out the OCTEON specific parts to a separate patch.
Yes, please do the factoring.
> diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
> index 780b520..d9c46a4 100644
> --- a/arch/mips/Kconfig
> +++ b/arch/mips/Kconfig
> @@ -1431,6 +1431,23 @@ config PAGE_SIZE_64KB
>
> endchoice
>
> +config MAPPED_KERNEL
> + bool "Mapped kernel"
> + help
> + Select this option if you want the kernel's code and data to
> + be in mapped memory. The kernel will be mapped using a
> + single wired TLB entry, thus reducing the number of
> + available TLB entries by one. Kernel modules will be able
> + to use a more efficient calling convention.
This is currently only supported on 64-bit processors, so this should
depend on CONFIG_64BIT.
> diff --git a/arch/mips/Makefile b/arch/mips/Makefile
> index 0bc2120..5468f6d 100644
> --- a/arch/mips/Makefile
> +++ b/arch/mips/Makefile
...
> @@ -662,7 +670,7 @@ OBJCOPYFLAGS += --remove-section=.reginfo
>
> CPPFLAGS_vmlinux.lds := \
> $(KBUILD_CFLAGS) \
> - -D"LOADADDR=$(load-y)" \
> + -D"LOADADDR=$(load-y)" $(PHYS_LOAD_ADDRESS) \
> -D"JIFFIES=$(JIFFIES)" \
> -D"DATAOFFSET=$(if $(dataoffset-y),$(dataoffset-y),0)"
It seems more consistent to just eliminate PHYS_LOAD_ADDRESS entirely
and add a line here reading:
-D"PHYSADDR=0x$(CONFIG_PHYS_LOAD_ADDRESS)" \
>
> diff --git a/arch/mips/include/asm/mach-cavium-octeon/kernel-entry-init.h b/arch/mips/include/asm/mach-cavium-octeon/kernel-entry-init.h
> index 0b2b5eb..bf36d82 100644
> --- a/arch/mips/include/asm/mach-cavium-octeon/kernel-entry-init.h
> +++ b/arch/mips/include/asm/mach-cavium-octeon/kernel-entry-init.h
> @@ -27,6 +27,56 @@
> # a3 = address of boot descriptor block
> .set push
> .set arch=octeon
> +#ifdef CONFIG_MAPPED_KERNEL
> + # Set up the TLB index 0 for wired access to kernel.
> + # Assume we were loaded with sufficient alignment so that we
> + # can cover the image with two pages.
This seems like a pretty big assumption. Possible ways to handle this:
o Generalize to handle n pages.
o Hang in a loop here if the assumption is not met
o Check later on whether the assumption was true and print a message.
I'm not really sure how to do this last one, though.
> + dla v0, _end
> + dla v1, _text
> + dsubu v0, v0, v1 # size of image
> + move v1, zero
> + li t1, -1 # shift count.
> +1: dsrl v0, v0, 1 # mask into v1
> + dsll v1, v1, 1
> + daddiu t1, t1, 1
> + ori v1, v1, 1
> + bne v0, zero, 1b
> + daddiu t2, t1, -6
> + mtc0 v1, $5, 0 # PageMask
> + dla t3, 0xffffffffc0000000 # kernel address
I think this should be CKSSEG rather than a magic constant.
> + dmtc0 t3, $10, 0 # EntryHi
> + bal 1f
> +1: dla v0, 0x7fffffff
Another magic constant; don't know if there is already a define that
really applies, though. Perhaps add something to asm-mips/inst.h?
> diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
> index 1055348..b44bcf8 100644
> --- a/arch/mips/kernel/traps.c
> +++ b/arch/mips/kernel/traps.c
> @@ -49,6 +49,8 @@
> #include <asm/stacktrace.h>
> #include <asm/irq.h>
>
> +#include "../mm/uasm.h"
This looks like it would be a good idea to consider moving uasm.h to
include/asm-mips, or possibly splitting it into two header files, one of
which would move to include/asm-mips.
> +
> extern void check_wait(void);
> extern asmlinkage void r4k_wait(void);
> extern asmlinkage void rollback_handle_int(void);
> @@ -1295,9 +1297,18 @@ void *set_except_vector(int n, void *addr)
>
> exception_handlers[n] = handler;
> if (n == 0 && cpu_has_divec) {
> - *(u32 *)(ebase + 0x200) = 0x08000000 |
> - (0x03ffffff & (handler >> 2));
> - local_flush_icache_range(ebase + 0x200, ebase + 0x204);
> + unsigned long jump_mask = ~((1 << 28) - 1);
The 28 is a magic constant specifying the number of bits of the offset
in a jump instruction. Perhaps define jump_mask in asm-mips/inst.h since
it is related to the instruction format?
> + u32 *buf = (u32 *)(ebase + 0x200);
> + unsigned int k0 = 26;
You are using k0 as a constant by defining it as a variable. You could
just have a #define here, but my suggestion is that it would be better
to add defines to asm-mips/inst.h (something like "#define REG_K0 26"
might be suitable for meeting this particular need)
> + if((handler & jump_mask) == ((ebase + 0x200) & jump_mask)) {
> + uasm_i_j(&buf, handler & jump_mask);
> + uasm_i_nop(&buf);
> + } else {
> + UASM_i_LA(&buf, k0, handler);
> + uasm_i_jr(&buf, k0);
> + uasm_i_nop(&buf);
> + }
> + local_flush_icache_range(ebase + 0x200, (unsigned long)buf);
> }
> return (void *)old_handler;
> }
> /*
> @@ -1670,9 +1683,9 @@ void __init trap_init(void)
> return; /* Already done */
> #endif
>
> - if (cpu_has_veic || cpu_has_vint)
> + if (cpu_has_veic || cpu_has_vint) {
> ebase = (unsigned long) alloc_bootmem_low_pages(0x200 + VECTORSPACING*64);
> - else {
> + } else {
Checkpatch will complain about this, and it doesn't really add value to
make the change.
> diff --git a/arch/mips/mm/page.c b/arch/mips/mm/page.c
> index 1417c64..0070aa0 100644
> --- a/arch/mips/mm/page.c
> +++ b/arch/mips/mm/page.c
> @@ -687,3 +687,9 @@ void copy_page(void *to, void *from)
> }
>
> #endif /* CONFIG_SIBYTE_DMA_PAGEOPS */
> +
> +#ifdef CONFIG_MAPPED_KERNEL
> +/* Initialized so it is not clobbered when .bss is zeroed. */
> +unsigned long phys_to_kernel_offset = 1;
> +unsigned long kernel_image_end = 1;
> +#endif
Clearly there is some magic happening here, but the such wizardry needs
more documentation. I can deduce that these must be overwritten before
we get to kernel_entry; who sets these?
I don't know for sure what kernel_image_end is, but I am guessing that
it is the physical address of the end of the kernel. If so, you can
eliminate it as a piece of magic by calculating it at run time as the
sum of the address of the start of the kernel and the size.
--
David VomLehn, dvomlehn@cisco.com
- - - - - Cisco - - - - -
This e-mail and any attachments may contain information which is confidential,
proprietary, privileged or otherwise protected by law. The information is solely
intended for the named addressee (or a person responsible for delivering it to
the addressee). If you are not the intended recipient of this message, you are
not authorized to read, print, retain, copy or disseminate this message or any
part of it. If you have received this e-mail in error, please notify the sender
immediately by return e-mail and delete it from your computer.
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] MIPS: Add option for running kernel in mapped address space.
2009-01-09 1:26 ` David VomLehn
@ 2009-01-09 2:33 ` David Daney
0 siblings, 0 replies; 3+ messages in thread
From: David Daney @ 2009-01-09 2:33 UTC (permalink / raw)
To: dvomlehn; +Cc: linux-mips
David VomLehn wrote:
> On Wed, 2009-01-07 at 17:41 -0800, David Daney wrote:
>> This is a preliminary patch to allow the kernel to run in mapped
>> address space via a wired TLB entry. Probably in a future version I
>> would factor out the OCTEON specific parts to a separate patch.
>
> Yes, please do the factoring.
Everything in good time. My real intent was to generate feedback about
the general ideas.
>
>> diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
>> index 780b520..d9c46a4 100644
>> --- a/arch/mips/Kconfig
>> +++ b/arch/mips/Kconfig
>> @@ -1431,6 +1431,23 @@ config PAGE_SIZE_64KB
>>
>> endchoice
>>
>> +config MAPPED_KERNEL
>> + bool "Mapped kernel"
>> + help
>> + Select this option if you want the kernel's code and data to
>> + be in mapped memory. The kernel will be mapped using a
>> + single wired TLB entry, thus reducing the number of
>> + available TLB entries by one. Kernel modules will be able
>> + to use a more efficient calling convention.
>
> This is currently only supported on 64-bit processors, so this should
> depend on CONFIG_64BIT.
It should be trivial to extend to 32-bit kernels as well. I may try it
on the mips32 based STB I have at home. But as it currently stands, you
are correct.
>
>> diff --git a/arch/mips/Makefile b/arch/mips/Makefile
>> index 0bc2120..5468f6d 100644
>> --- a/arch/mips/Makefile
>> +++ b/arch/mips/Makefile
> ...
>> @@ -662,7 +670,7 @@ OBJCOPYFLAGS += --remove-section=.reginfo
>>
>> CPPFLAGS_vmlinux.lds := \
>> $(KBUILD_CFLAGS) \
>> - -D"LOADADDR=$(load-y)" \
>> + -D"LOADADDR=$(load-y)" $(PHYS_LOAD_ADDRESS) \
>> -D"JIFFIES=$(JIFFIES)" \
>> -D"DATAOFFSET=$(if $(dataoffset-y),$(dataoffset-y),0)"
>
> It seems more consistent to just eliminate PHYS_LOAD_ADDRESS entirely
> and add a line here reading:
> -D"PHYSADDR=0x$(CONFIG_PHYS_LOAD_ADDRESS)" \
There is some macro trickery in vmlinux.lds.S that checks to see if it
is defined, so I cannot unconditionally define it.
>
>>
>> diff --git a/arch/mips/include/asm/mach-cavium-octeon/kernel-entry-init.h b/arch/mips/include/asm/mach-cavium-octeon/kernel-entry-init.h
>> index 0b2b5eb..bf36d82 100644
>> --- a/arch/mips/include/asm/mach-cavium-octeon/kernel-entry-init.h
>> +++ b/arch/mips/include/asm/mach-cavium-octeon/kernel-entry-init.h
>> @@ -27,6 +27,56 @@
>> # a3 = address of boot descriptor block
>> .set push
>> .set arch=octeon
>> +#ifdef CONFIG_MAPPED_KERNEL
>> + # Set up the TLB index 0 for wired access to kernel.
>> + # Assume we were loaded with sufficient alignment so that we
>> + # can cover the image with two pages.
>
> This seems like a pretty big assumption. Possible ways to handle this:
> o Generalize to handle n pages.
This is an optimization, burning through TLB entries is not going to
help things.
> o Hang in a loop here if the assumption is not met
Possible.
> o Check later on whether the assumption was true and print a message.
> I'm not really sure how to do this last one, though.
Also possible.
This is all very low-level board code, if you want the optimization, you
need to load at a suitable physical address.
>
>> + dla v0, _end
>> + dla v1, _text
>> + dsubu v0, v0, v1 # size of image
>> + move v1, zero
>> + li t1, -1 # shift count.
>> +1: dsrl v0, v0, 1 # mask into v1
>> + dsll v1, v1, 1
>> + daddiu t1, t1, 1
>> + ori v1, v1, 1
>> + bne v0, zero, 1b
>> + daddiu t2, t1, -6
>> + mtc0 v1, $5, 0 # PageMask
>> + dla t3, 0xffffffffc0000000 # kernel address
>
> I think this should be CKSSEG rather than a magic constant.
>
>> + dmtc0 t3, $10, 0 # EntryHi
>> + bal 1f
>> +1: dla v0, 0x7fffffff
>
> Another magic constant; don't know if there is already a define that
> really applies, though. Perhaps add something to asm-mips/inst.h?
>
Both are worth investigating. Each board could (and may have to) do it
differently.
>> diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
>> index 1055348..b44bcf8 100644
>> --- a/arch/mips/kernel/traps.c
>> +++ b/arch/mips/kernel/traps.c
>> @@ -49,6 +49,8 @@
>> #include <asm/stacktrace.h>
>> #include <asm/irq.h>
>>
>> +#include "../mm/uasm.h"
>
> This looks like it would be a good idea to consider moving uasm.h to
> include/asm-mips, or possibly splitting it into two header files, one of
> which would move to include/asm-mips.
>
That was my thought as well. This being a quick-and-dirty hack, I took
the low road and did it this way.
>> +
>> extern void check_wait(void);
>> extern asmlinkage void r4k_wait(void);
>> extern asmlinkage void rollback_handle_int(void);
>> @@ -1295,9 +1297,18 @@ void *set_except_vector(int n, void *addr)
>>
>> exception_handlers[n] = handler;
>> if (n == 0 && cpu_has_divec) {
>> - *(u32 *)(ebase + 0x200) = 0x08000000 |
>> - (0x03ffffff & (handler >> 2));
>> - local_flush_icache_range(ebase + 0x200, ebase + 0x204);
>> + unsigned long jump_mask = ~((1 << 28) - 1);
>
> The 28 is a magic constant specifying the number of bits of the offset
> in a jump instruction. Perhaps define jump_mask in asm-mips/inst.h since
> it is related to the instruction format?
Correct.
>
>> + u32 *buf = (u32 *)(ebase + 0x200);
>> + unsigned int k0 = 26;
>
> You are using k0 as a constant by defining it as a variable. You could
> just have a #define here, but my suggestion is that it would be better
> to add defines to asm-mips/inst.h (something like "#define REG_K0 26"
> might be suitable for meeting this particular need)
Yes, the constants should probably be factored out of the TLB and page
code. Then they could be used here as well.
[...]
>>
>> - if (cpu_has_veic || cpu_has_vint)
>> + if (cpu_has_veic || cpu_has_vint) {
>> ebase = (unsigned long) alloc_bootmem_low_pages(0x200 + VECTORSPACING*64);
>> - else {
>> + } else {
>
> Checkpatch will complain about this, and it doesn't really add value to
> make the change.
>
IANACPL (I am not a checkpatch lawyer), but I think it is correct. If
one clause of an if has braces they both should. However that was left
over from my debugging and if it were to be changed, should be part of a
code cleanup patch.
>> diff --git a/arch/mips/mm/page.c b/arch/mips/mm/page.c
>> index 1417c64..0070aa0 100644
>> --- a/arch/mips/mm/page.c
>> +++ b/arch/mips/mm/page.c
>> @@ -687,3 +687,9 @@ void copy_page(void *to, void *from)
>> }
>>
>> #endif /* CONFIG_SIBYTE_DMA_PAGEOPS */
>> +
>> +#ifdef CONFIG_MAPPED_KERNEL
>> +/* Initialized so it is not clobbered when .bss is zeroed. */
>> +unsigned long phys_to_kernel_offset = 1;
>> +unsigned long kernel_image_end = 1;
>> +#endif
>
> Clearly there is some magic happening here, but the such wizardry needs
> more documentation.
Clearly.
> I can deduce that these must be overwritten before
> we get to kernel_entry;
One of the first things done at kernel_entry is to zero out .bss, if you
want to communicate with things that happen before kernel_entry, you
cannot use .bss.
> who sets these?
The code in kernel-entry-init.h
> I don't know for sure what kernel_image_end is, but I am guessing that
> it is the physical address of the end of the kernel.
It is the virtual address of the first page past the kernel's virtual
mapping. This is where we can start mapping modules.
David Daney
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2009-01-09 2:34 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-01-08 1:41 [PATCH] MIPS: Add option for running kernel in mapped address space David Daney
2009-01-09 1:26 ` David VomLehn
2009-01-09 2:33 ` David Daney
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.