When attempting to load kadb from a Solaris 8 CD at boot, it seems that in order for kadb to allocate enough memory to load the kernel (and its modules) the /openprom/aligned-allocator property must be present with length zero.
This has the additional side-effect that OpenBIOS memory allocations are redirected to a new romvec offset when this property is detected, which appears to have a similar interface to obp_dumb_memalloc() but with an extra alignment parameter. Hence we include a simple implementation which seems to be enough to be able to get kadb to load and attach to the kernel.
--- openbios-devel/arch/sparc32/call-romvec.S | 1 + openbios-devel/arch/sparc32/lib.c | 28 +++++++++++++++++----------- openbios-devel/arch/sparc32/openprom.h | 5 ++++- openbios-devel/arch/sparc32/romvec.c | 2 ++ openbios-devel/arch/sparc32/romvec.h | 2 ++ openbios-devel/arch/sparc32/tree.fs | 3 +++ 6 files changed, 29 insertions(+), 12 deletions(-)
diff --git a/openbios-devel/arch/sparc32/call-romvec.S b/openbios-devel/arch/sparc32/call-romvec.S index 1e8f754..2b2dfe0 100644 --- a/openbios-devel/arch/sparc32/call-romvec.S +++ b/openbios-devel/arch/sparc32/call-romvec.S @@ -89,4 +89,5 @@ ROMVEC_HANDLER(obp_proplen) ROMVEC_HANDLER(obp_getprop) ROMVEC_HANDLER(obp_setprop) ROMVEC_HANDLER(obp_nextprop) +ROMVEC_HANDLER(obp_align_memalloc)
diff --git a/openbios-devel/arch/sparc32/lib.c b/openbios-devel/arch/sparc32/lib.c index 01fa570..b975fd4 100644 --- a/openbios-devel/arch/sparc32/lib.c +++ b/openbios-devel/arch/sparc32/lib.c @@ -347,10 +347,25 @@ void ofmem_arch_early_map_pages(phys_addr_t phys, ucell virt, ucell size, ucell map_pages(phys, virt, size, mode); }
-char *obp_dumb_memalloc(char *va, unsigned int size) +char *obp_align_memalloc(char *va, unsigned int size, unsigned int align) { phys_addr_t phys; ucell virt; + + /* Claim physical memory */ + phys = ofmem_claim_phys(-1, size, align); + + /* Claim virtual memory */ + virt = ofmem_claim_virt(pointer2cell(va), size, 0); + + /* Map the memory */ + ofmem_map(phys, virt, size, ofmem_arch_default_translation_mode(phys)); + + return cell2pointer(virt); +} + +char *obp_dumb_memalloc(char *va, unsigned int size) +{ unsigned long align; int i;
@@ -371,16 +386,7 @@ char *obp_dumb_memalloc(char *va, unsigned int size) align++; }
- /* Claim physical memory */ - phys = ofmem_claim_phys(-1, size, align); - - /* Claim virtual memory */ - virt = ofmem_claim_virt(pointer2cell(va), size, 0); - - /* Map the memory */ - ofmem_map(phys, virt, size, ofmem_arch_default_translation_mode(phys)); - - return cell2pointer(virt); + return obp_align_memalloc(va, size, align); }
void obp_dumb_memfree(__attribute__((unused))char *va, diff --git a/openbios-devel/arch/sparc32/openprom.h b/openbios-devel/arch/sparc32/openprom.h index 0a2074b..5f05014 100644 --- a/openbios-devel/arch/sparc32/openprom.h +++ b/openbios-devel/arch/sparc32/openprom.h @@ -135,7 +135,10 @@ struct linux_romvec { struct linux_bootargs_v2 pv_v2bootargs; struct linux_dev_v2_funcs pv_v2devops;
- int filler[15]; + /* Allocate memory to specified alignment */ + char * (*pv_align_mem_alloc)(char *va, unsigned int size, unsigned int align); + + int filler[11];
/* This one is sun4c/sun4 only. */ void (*pv_setctxt)(int ctxt, char *va, int pmeg); diff --git a/openbios-devel/arch/sparc32/romvec.c b/openbios-devel/arch/sparc32/romvec.c index 843b9f4..463181d 100644 --- a/openbios-devel/arch/sparc32/romvec.c +++ b/openbios-devel/arch/sparc32/romvec.c @@ -508,6 +508,8 @@ init_openprom(void) fword("open-dev"); obp_fd_stdout = POP();
+ romvec0.pv_align_mem_alloc = obp_align_memalloc_handler; + romvec0.v3_cpustart = obp_cpustart_handler; romvec0.v3_cpustop = obp_cpustop_handler; romvec0.v3_cpuidle = obp_cpuidle_handler; diff --git a/openbios-devel/arch/sparc32/romvec.h b/openbios-devel/arch/sparc32/romvec.h index d5103d1..816109c 100644 --- a/openbios-devel/arch/sparc32/romvec.h +++ b/openbios-devel/arch/sparc32/romvec.h @@ -74,3 +74,5 @@ int obp_setprop_handler(__attribute__((unused)) int node, __attribute__((unused)) int len); const char *obp_nextprop(int node, const char *name); const char *obp_nextprop_handler(int node, const char *name); +char *obp_align_memalloc(char *va, unsigned int size, unsigned int align); +char *obp_align_memalloc_handler(char *va, unsigned int size, unsigned int align); diff --git a/openbios-devel/arch/sparc32/tree.fs b/openbios-devel/arch/sparc32/tree.fs index c0b08bd..f9a0406 100644 --- a/openbios-devel/arch/sparc32/tree.fs +++ b/openbios-devel/arch/sparc32/tree.fs @@ -125,3 +125,6 @@ finish-device
" /options" find-device " disk" encode-string " boot-from" property + +" /openprom" find-device + 0 0 " aligned-allocator" property
On Tue, Apr 19, 2011 at 1:31 AM, Mark Cave-Ayland mark.cave-ayland@siriusit.co.uk wrote:
When attempting to load kadb from a Solaris 8 CD at boot, it seems that in order for kadb to allocate enough memory to load the kernel (and its modules) the /openprom/aligned-allocator property must be present with length zero.
Awesome work!
This has the additional side-effect that OpenBIOS memory allocations are redirected to a new romvec offset when this property is detected, which appears to have a similar interface to obp_dumb_memalloc() but with an extra alignment parameter. Hence we include a simple implementation which seems to be enough to be able to get kadb to load and attach to the kernel.
openbios-devel/arch/sparc32/call-romvec.S | 1 + openbios-devel/arch/sparc32/lib.c | 28 +++++++++++++++++----------- openbios-devel/arch/sparc32/openprom.h | 5 ++++- openbios-devel/arch/sparc32/romvec.c | 2 ++ openbios-devel/arch/sparc32/romvec.h | 2 ++ openbios-devel/arch/sparc32/tree.fs | 3 +++ 6 files changed, 29 insertions(+), 12 deletions(-)
diff --git a/openbios-devel/arch/sparc32/call-romvec.S b/openbios-devel/arch/sparc32/call-romvec.S index 1e8f754..2b2dfe0 100644 --- a/openbios-devel/arch/sparc32/call-romvec.S +++ b/openbios-devel/arch/sparc32/call-romvec.S @@ -89,4 +89,5 @@ ROMVEC_HANDLER(obp_proplen) ROMVEC_HANDLER(obp_getprop) ROMVEC_HANDLER(obp_setprop) ROMVEC_HANDLER(obp_nextprop) +ROMVEC_HANDLER(obp_align_memalloc)
diff --git a/openbios-devel/arch/sparc32/lib.c b/openbios-devel/arch/sparc32/lib.c index 01fa570..b975fd4 100644 --- a/openbios-devel/arch/sparc32/lib.c +++ b/openbios-devel/arch/sparc32/lib.c @@ -347,10 +347,25 @@ void ofmem_arch_early_map_pages(phys_addr_t phys, ucell virt, ucell size, ucell map_pages(phys, virt, size, mode); }
-char *obp_dumb_memalloc(char *va, unsigned int size) +char *obp_align_memalloc(char *va, unsigned int size, unsigned int align) { phys_addr_t phys; ucell virt;
- /* Claim physical memory */
- phys = ofmem_claim_phys(-1, size, align);
- /* Claim virtual memory */
- virt = ofmem_claim_virt(pointer2cell(va), size, 0);
- /* Map the memory */
- ofmem_map(phys, virt, size, ofmem_arch_default_translation_mode(phys));
- return cell2pointer(virt);
+}
+char *obp_dumb_memalloc(char *va, unsigned int size) +{ unsigned long align; int i;
@@ -371,16 +386,7 @@ char *obp_dumb_memalloc(char *va, unsigned int size) align++; }
- /* Claim physical memory */
- phys = ofmem_claim_phys(-1, size, align);
- /* Claim virtual memory */
- virt = ofmem_claim_virt(pointer2cell(va), size, 0);
- /* Map the memory */
- ofmem_map(phys, virt, size, ofmem_arch_default_translation_mode(phys));
- return cell2pointer(virt);
- return obp_align_memalloc(va, size, align);
}
void obp_dumb_memfree(__attribute__((unused))char *va, diff --git a/openbios-devel/arch/sparc32/openprom.h b/openbios-devel/arch/sparc32/openprom.h index 0a2074b..5f05014 100644 --- a/openbios-devel/arch/sparc32/openprom.h +++ b/openbios-devel/arch/sparc32/openprom.h @@ -135,7 +135,10 @@ struct linux_romvec { struct linux_bootargs_v2 pv_v2bootargs; struct linux_dev_v2_funcs pv_v2devops;
- int filler[15];
- /* Allocate memory to specified alignment */
- char * (*pv_align_mem_alloc)(char *va, unsigned int size, unsigned int align);
- int filler[11];
This would shorten the structure by 12 bytes, please use 14 instead of 11.
On 19/04/11 20:31, Blue Swirl wrote:
-char *obp_dumb_memalloc(char *va, unsigned int size) +char *obp_align_memalloc(char *va, unsigned int size, unsigned int align)
Apparently there is a v2 and a v3 version of malloc() within romvec, so it's pretty likely that this is the v3 version given its position within the structure. I'll rename this to something that makes it more obvious it is v3 related.
void obp_dumb_memfree(__attribute__((unused))char *va, diff --git a/openbios-devel/arch/sparc32/openprom.h b/openbios-devel/arch/sparc32/openprom.h index 0a2074b..5f05014 100644 --- a/openbios-devel/arch/sparc32/openprom.h +++ b/openbios-devel/arch/sparc32/openprom.h @@ -135,7 +135,10 @@ struct linux_romvec { struct linux_bootargs_v2 pv_v2bootargs; struct linux_dev_v2_funcs pv_v2devops;
int filler[15];
/* Allocate memory to specified alignment */
char * (*pv_align_mem_alloc)(char *va, unsigned int size, unsigned int align);
int filler[11];
This would shorten the structure by 12 bytes, please use 14 instead of 11.
Ah yes, my mistake - it's an int rather than a char. Will re-submit shortly with these two changes.
ATB,
Mark.