* How can I jump to non-linux address space? @ 2001-10-04 1:10 Ian Thompson 2001-10-04 9:04 ` Helge Hafting 2001-10-04 20:35 ` Russell King 0 siblings, 2 replies; 12+ messages in thread From: Ian Thompson @ 2001-10-04 1:10 UTC (permalink / raw) To: linux-kernel Hi all, I'm sorry if this is off-topic, but I wasn't sure where else to ask... My kernel is running from RAM, and I want to jump to an address in ROM (which unfortunately, the kernel doesn't seem to know anything about). I don't plan on trying to resume the kernel after doing this. However, I'm getting a prefetch abort. If I try and load the data, I get a similar error: "Unable to handle kernel paging request at virtual address 00003000" where 0x3000 is the ROM address I'm trying to jump to / load from. How can I pass execution to this address? Do I have to turn off the MMU? FYI, I'm running a 2.2 variant on an XScale, and used inline assembly to generate the load & the branch. Thanks for your help, -ian ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: How can I jump to non-linux address space? 2001-10-04 1:10 How can I jump to non-linux address space? Ian Thompson @ 2001-10-04 9:04 ` Helge Hafting 2001-10-04 19:40 ` Ian Thompson 2001-10-04 20:35 ` Russell King 1 sibling, 1 reply; 12+ messages in thread From: Helge Hafting @ 2001-10-04 9:04 UTC (permalink / raw) To: Ian Thompson; +Cc: linux-kernel Ian Thompson wrote: > > Hi all, > > I'm sorry if this is off-topic, but I wasn't sure where else to ask... > > My kernel is running from RAM, and I want to jump to an address in ROM > (which unfortunately, the kernel doesn't seem to know anything about). I The kernel can get to know - all you need is code that maps the ROM address range into some available virtual address range. Look at device driver code - they do such mapping for ROM and/or memory-based io regions. > don't plan on trying to resume the kernel after doing this. However, I'm > getting a prefetch abort. If I try and load the data, I get a similar > error: "Unable to handle kernel paging request at virtual address 00003000" > where 0x3000 is the ROM address I'm trying to jump to / load from. How can > I pass execution to this address? Do I have to turn off the MMU? How to set up the cpu before jumping to a ROM that won't return can be tricky indeed. This depends on what that ROM code expect! Do that ROM code work when the MMU has remapped its adresses so it appears at some adress completely different from the bus address? (only if it contains relative jumps only - no absolute addresses.) Does it work with 4G segments? Does it work at all in protected mode, with all interrupts routed to the linux kernel instead of the bios? Does this code expect to find something (data, device interfaces, vga memory) at certain addresses? If so, this must be mapped too. For linux moves all this around. In practise, existing ROM's tend to assume that the machine is in a state close to what the bios initializes it to, with 64k segments, no MMU, and a lot of assumptions about how interrupts and hw devices are set up. _All_ of these assumptions break after you start linux, and resetting everything is so hard that it is usually done by running the bios cold boot code. Helge Hafting ^ permalink raw reply [flat|nested] 12+ messages in thread
* RE: How can I jump to non-linux address space? 2001-10-04 9:04 ` Helge Hafting @ 2001-10-04 19:40 ` Ian Thompson 2001-10-04 20:32 ` Richard B. Johnson 0 siblings, 1 reply; 12+ messages in thread From: Ian Thompson @ 2001-10-04 19:40 UTC (permalink / raw) To: Helge Hafting; +Cc: linux-kernel Helge, Thanks for your advice! It's brought up a couple of other question, if you don't mind: > The kernel can get to know - all you need is code that maps the > ROM address range into some available virtual address range. > Look at device driver code - they do such mapping for ROM and/or > memory-based io regions. I've seen the mapping of the single RAM address range, but I don't see where it is possible to add in another range for ROM. What functions should I look for that do this mapping? > Do that ROM code work when the MMU has remapped its adresses so it > appears at some adress completely different from the bus address? (only > if it contains relative jumps only - no absolute addresses.) Does > it work with 4G segments? Does it work at all in protected mode, > with all interrupts routed to the linux kernel instead of the bios? > Does this code expect to find something (data, device interfaces, > vga memory) at certain addresses? If so, this must be mapped too. I've run this code (in ROM) successfully before starting the kernel. I believe the cache is disabled, and interrupts are not needed (and are off). The code does not refer to anything within the kernel. I've tried turning off the MMU completely before branching, but this seems to hang the system. =( Any ideas of what I should look for to turn off, aside from just shutting down the MMU? If I map the ROM address range into a virtual addr range, won't I run into problems once I'm running the code, such as physical addresses being interpreted by virtual ones? btw, this is running on an XScale (strongARM). Thanks again, -ian ^ permalink raw reply [flat|nested] 12+ messages in thread
* RE: How can I jump to non-linux address space? 2001-10-04 19:40 ` Ian Thompson @ 2001-10-04 20:32 ` Richard B. Johnson 2001-10-05 0:35 ` Ian Thompson 0 siblings, 1 reply; 12+ messages in thread From: Richard B. Johnson @ 2001-10-04 20:32 UTC (permalink / raw) To: Ian Thompson; +Cc: Helge Hafting, linux-kernel On Thu, 4 Oct 2001, Ian Thompson wrote: > Helge, > > Thanks for your advice! It's brought up a couple of other question, if you > don't mind: > > > The kernel can get to know - all you need is code that maps the > > ROM address range into some available virtual address range. > > Look at device driver code - they do such mapping for ROM and/or > > memory-based io regions. > > I've seen the mapping of the single RAM address range, but I don't see where > it is possible to add in another range for ROM. What functions should I > look for that do this mapping? > > > Do that ROM code work when the MMU has remapped its adresses so it > > appears at some adress completely different from the bus address? (only > > if it contains relative jumps only - no absolute addresses.) Does > > it work with 4G segments? Does it work at all in protected mode, > > with all interrupts routed to the linux kernel instead of the bios? > > Does this code expect to find something (data, device interfaces, > > vga memory) at certain addresses? If so, this must be mapped too. > > I've run this code (in ROM) successfully before starting the kernel. I > believe the cache is disabled, and interrupts are not needed (and are off). > The code does not refer to anything within the kernel. I've tried turning > off the MMU completely before branching, but this seems to hang the system. > =( > > Any ideas of what I should look for to turn off, aside from just shutting > down the MMU? If I map the ROM address range into a virtual addr range, > won't I run into problems once I'm running the code, such as physical > addresses being interpreted by virtual ones? > > btw, this is running on an XScale (strongARM). > > Thanks again, > -ian All kernel addresses, including "physical" addresses are virtual. There is a PTE to map your specific memory area, on a page-by-page basis, to a virtual address. You are normally accessing memory using that virtual address (both code and data). If you want to turn OFF the virtual addressing, you have to first jump or call a procedure, that is properly relocated, somewhere that the virtual and physical addresses are the same. The first one megabyte is such a location. It is complex and has to be done in the correct order or else you can't "get back". A typical way, on an ix86, is to make a binary array from the code you want to execute, relocated from an object file, to some offset such as 0x1000. You use ioremap() to create a virtual address from 0x1000. Then you copy the relocated code, currently in some array, to the relocated address (0x1000), using the cookie returned from ioremap(). Then you disable interrupts on your local CPU via a spinlock, you make a long (FAR) call to your relocated code. In the code, you can disable the paging bit and set DS, ES to the page-table selector, which looks at linear addressing. Now you can see and access everything as 32-bit linear address-space. Careful, you can't allow interrupts and you can't use the stack because neither it, nor the stack-selector has been set. You can do "your" thing, with global memory then you restore the previous selectors to DS and ES, re-enable paging, then do a FAR return. The code after the return unlocks the spin-lock and you are home free. I any step isn't done correctly, you will crash the processor ;^). This shows up as though you hit the reset switch. # insmod module.o <SPLAT> <FLASH> Award Modular BIOS V45pg Copyright(c) 1998 Award Software, Inc. Memory test : 0011240 Ok Pres DEL to enter SETUP Cheers, Dick Johnson Penguin : Linux version 2.4.1 on an i686 machine (799.53 BogoMips). I was going to compile a list of innovations that could be attributed to Microsoft. Once I realized that Ctrl-Alt-Del was handled in the BIOS, I found that there aren't any. ^ permalink raw reply [flat|nested] 12+ messages in thread
* RE: How can I jump to non-linux address space? 2001-10-04 20:32 ` Richard B. Johnson @ 2001-10-05 0:35 ` Ian Thompson 2001-10-05 7:55 ` Russell King 2001-10-08 12:51 ` Richard B. Johnson 0 siblings, 2 replies; 12+ messages in thread From: Ian Thompson @ 2001-10-05 0:35 UTC (permalink / raw) To: root; +Cc: Helge Hafting, linux-kernel Hey Dick, Thanks for the help! A couple more questions for you... > You use ioremap() to create a virtual address from 0x1000. Then > you copy the relocated code, currently in some array, to the relocated > address (0x1000), using the cookie returned from ioremap(). How does this make the virtual address the same as the physical address? Or are addr's in the first page (or 1st MB?) automatically mapped to the same address when you call ioremap()? I printed out the __ioremap() addr's for 0x1000 and 0x3000, and neither of the virt addr's were equal to the physical ones. I tried something slightly different, which didn't work... Should it have? What I did was put the code to turn off the MMU at physical address 0x3000, and jumped to it (via branching to __ioremap(0x3000)). I think the branch is working, since I can load the correct instruction via this reloc'ed address. However, running the code that turns off the MMU instead reboots the machine. =( > In the code, you can disable the paging bit and set DS, ES to the > page-table selector, which looks at linear addressing. Now you can > see and access everything as 32-bit linear address-space. Should I be looking for something else to twiddle instead of the MMU bit in the CPU register? You mentioned the paging bit; is this different? Also, what are DS & ES? gracias, -ian ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: How can I jump to non-linux address space? 2001-10-05 0:35 ` Ian Thompson @ 2001-10-05 7:55 ` Russell King 2001-10-08 12:51 ` Richard B. Johnson 1 sibling, 0 replies; 12+ messages in thread From: Russell King @ 2001-10-05 7:55 UTC (permalink / raw) To: Ian Thompson; +Cc: root, Helge Hafting, linux-kernel On Thu, Oct 04, 2001 at 05:35:51PM -0700, Ian Thompson wrote: > Hey Dick, > Should I be looking for something else to twiddle instead of the MMU bit in > the CPU register? You mentioned the paging bit; is this different? Also, > what are DS & ES? Dick is talking about x86 hardware, not your ARM hardware. -- Russell King (rmk@arm.linux.org.uk) The developer of ARM Linux http://www.arm.linux.org.uk/personal/aboutme.html ^ permalink raw reply [flat|nested] 12+ messages in thread
* RE: How can I jump to non-linux address space? 2001-10-05 0:35 ` Ian Thompson 2001-10-05 7:55 ` Russell King @ 2001-10-08 12:51 ` Richard B. Johnson 1 sibling, 0 replies; 12+ messages in thread From: Richard B. Johnson @ 2001-10-08 12:51 UTC (permalink / raw) To: Ian Thompson; +Cc: Helge Hafting, linux-kernel On Thu, 4 Oct 2001, Ian Thompson wrote: > Hey Dick, > > Thanks for the help! A couple more questions for you... > > > You use ioremap() to create a virtual address from 0x1000. Then > > you copy the relocated code, currently in some array, to the relocated > > address (0x1000), using the cookie returned from ioremap(). > > How does this make the virtual address the same as the physical address? Or > are addr's in the first page (or 1st MB?) automatically mapped to the same > address when you call ioremap()? I printed out the __ioremap() addr's for > 0x1000 and 0x3000, and neither of the virt addr's were equal to the physical > ones. > [Snipped...] I was refering to Intel, not ARM hardware. You can look at the setup code in your architecture specific tree and see if you can figure it out. I have never even seen ARM hardware, much less used it so I can't help there. FYI, what you get from ioremap() is not a number that will mean anything, even when it's mapped to the physical address. Often, on some kernel versions, just to prevent module writers from cheating, it is poisoned so it only works with the defined macros. Therefore, it is a "cookie", not something you can initialize a pointer with. However, in Intel, for hacking only, the address that you can use to initialize a pointer with is the address you re-mapped, ORed with PAGE_OFFSET. If the address is below 1 megabyte, there is a 1:1 mapping of virtual to physical addresses in the Intel Linux kernel. This allows the page table to exist at an address that can be accessed from 32-bit linear-mode startup. This is useful if you want to access something physical. For instance if you want to find the physical address of bad memory. A user-mode memory checker can exercise memory until something failed. Then it can write some magic numbers on both sides of the failing address. A kernel module could then search for the magic numbers, returning the 32-bit linear offset of the bad memory. This is quicker than writing a module to scan all the PTEs, returning the translation offset. Cheers, Dick Johnson Penguin : Linux version 2.4.1 on an i686 machine (799.53 BogoMips). I was going to compile a list of innovations that could be attributed to Microsoft. Once I realized that Ctrl-Alt-Del was handled in the BIOS, I found that there aren't any. ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: How can I jump to non-linux address space? 2001-10-04 1:10 How can I jump to non-linux address space? Ian Thompson 2001-10-04 9:04 ` Helge Hafting @ 2001-10-04 20:35 ` Russell King 2001-10-06 0:38 ` Ian Thompson 1 sibling, 1 reply; 12+ messages in thread From: Russell King @ 2001-10-04 20:35 UTC (permalink / raw) To: Ian Thompson; +Cc: linux-kernel On Wed, Oct 03, 2001 at 06:10:31PM -0700, Ian Thompson wrote: > My kernel is running from RAM, and I want to jump to an address in ROM > (which unfortunately, the kernel doesn't seem to know anything about). Ok, its like you're rebooting, correct? > I don't plan on trying to resume the kernel after doing this. However, > I'm getting a prefetch abort. That's because your address range for the ROM isn't mapped - when Linux starts on ARM, it unmaps virtually everything, and remaps only the address ranges it wants to use. > How can I pass execution to this address? Do I have to turn off the MMU? Essentially, you have 2 choices: 1. Turn off the MMU. 2. insert a 1:1 physical to virtual mapping for the ROM and call the code. (with interrupts disabled). Which one works depends on what the ROM code requires. There is an example of (1) in the current ARM kernel sources - the RiscPC port uses this method to reboot - we can't activate the hardware reset line on these machines, so our only option is to use this method. -- Russell King (rmk@arm.linux.org.uk) The developer of ARM Linux http://www.arm.linux.org.uk/personal/aboutme.html ^ permalink raw reply [flat|nested] 12+ messages in thread
* RE: How can I jump to non-linux address space? 2001-10-04 20:35 ` Russell King @ 2001-10-06 0:38 ` Ian Thompson 2001-10-06 7:57 ` Russell King 0 siblings, 1 reply; 12+ messages in thread From: Ian Thompson @ 2001-10-06 0:38 UTC (permalink / raw) To: Russell King; +Cc: linux-kernel > Essentially, you have 2 choices: > > 1. Turn off the MMU. > 2. insert a 1:1 physical to virtual mapping for the ROM and call the code. > (with interrupts disabled). > > Which one works depends on what the ROM code requires. > > There is an example of (1) in the current ARM kernel sources - the RiscPC > port uses this method to reboot - we can't activate the hardware reset line > on these machines, so our only option is to use this method. I tried both of these, and I must be doing something wrong. For (1), I grabbed the code you mentioned from the RiscPC port (setup_mm_for_reboot() and some code from the soft reset routine). After calling setup_mm_for_reboot, if I call __ioremap(), the processor hangs. If I shut down the MMU, I get the same results. Where would be a good place to find an example of how to implement your second suggestion? thanks. sorry to keep bothering you. i'll also try asking on the arm newsgroup... -ian ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: How can I jump to non-linux address space? 2001-10-06 0:38 ` Ian Thompson @ 2001-10-06 7:57 ` Russell King 2001-10-08 17:43 ` Ian Thompson 0 siblings, 1 reply; 12+ messages in thread From: Russell King @ 2001-10-06 7:57 UTC (permalink / raw) To: Ian Thompson; +Cc: linux-kernel On Fri, Oct 05, 2001 at 05:38:53PM -0700, Ian Thompson wrote: > I tried both of these, and I must be doing something wrong. For (1), I > grabbed the code you mentioned from the RiscPC port (setup_mm_for_reboot() > and some code from the soft reset routine). After calling > setup_mm_for_reboot, if I call __ioremap(), the processor hangs. If I shut > down the MMU, I get the same results. You will need to disable interrupts if the machine vectors are located at address 0 (check your boot logs with a recent kernel for a message like "Vectors relocated to ..."). It's probably best to call cpu_proc_fin(), setup_mm_for_reboot() and cpu_reset(address) directly rather than making your own copy - these functions already do the right things for you. setup_mm_for_reboot() will remap all of user space with a 1:1 virtual to physical mapping, and hopefully on the Xscale, the two cpu_* functions do the intended setup for this (I've not reviewed the xscale stuff in any great detail yet though). -- Russell King (rmk@arm.linux.org.uk) The developer of ARM Linux http://www.arm.linux.org.uk/personal/aboutme.html ^ permalink raw reply [flat|nested] 12+ messages in thread
* RE: How can I jump to non-linux address space? 2001-10-06 7:57 ` Russell King @ 2001-10-08 17:43 ` Ian Thompson 2001-10-08 20:01 ` Russell King 0 siblings, 1 reply; 12+ messages in thread From: Ian Thompson @ 2001-10-08 17:43 UTC (permalink / raw) To: Russell King; +Cc: linux-kernel > functions already do the right things for you. setup_mm_for_reboot() > will remap all of user space with a 1:1 virtual to physical mapping, Am I correct in assuming that this will not remap the kernel address space? If I'm trying to jump from the kernel to this physical address, will I need to go through user space first? -ian ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: How can I jump to non-linux address space? 2001-10-08 17:43 ` Ian Thompson @ 2001-10-08 20:01 ` Russell King 0 siblings, 0 replies; 12+ messages in thread From: Russell King @ 2001-10-08 20:01 UTC (permalink / raw) To: Ian Thompson; +Cc: linux-kernel On Mon, Oct 08, 2001 at 10:43:45AM -0700, Ian Thompson wrote: > Am I correct in assuming that this will not remap the kernel address space? > If I'm trying to jump from the kernel to this physical address, will I need > to go through user space first? If you want to execute code linked at address 0x3000, then you need to execute it at address 0x3000. Note that turning off the MMU will effectively change all the memory mappings. -- Russell King (rmk@arm.linux.org.uk) The developer of ARM Linux http://www.arm.linux.org.uk/personal/aboutme.html ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2001-10-08 20:01 UTC | newest] Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2001-10-04 1:10 How can I jump to non-linux address space? Ian Thompson 2001-10-04 9:04 ` Helge Hafting 2001-10-04 19:40 ` Ian Thompson 2001-10-04 20:32 ` Richard B. Johnson 2001-10-05 0:35 ` Ian Thompson 2001-10-05 7:55 ` Russell King 2001-10-08 12:51 ` Richard B. Johnson 2001-10-04 20:35 ` Russell King 2001-10-06 0:38 ` Ian Thompson 2001-10-06 7:57 ` Russell King 2001-10-08 17:43 ` Ian Thompson 2001-10-08 20:01 ` Russell King
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).