I’m currently developing a simple trustzone device driver running in Normal World to communicate with Genode in Secure World. I’m using IMX53 QSB, Genode 15.02 as Secure OS, and customized Linux as OS for Normal World.
In Normal World, my simple device driver calls smc instruction inside module_init(). The instruction is invoked with the command structure (named by “struct smc_cmd”). The physical address of "struct smc_cmd" is passing to Genode via _vm->state()->r1. There exists two physical addresses inside “struct smc_cmd": one for request buffer and the other for response buffer where the response buffer is allocated by kzalloc(). For the address conversion, I used virt_to_phys().
In Secure World (Genode), I’m modifying the tz_vmm source code for this experiment. I’m succeed in reading the request buffer from Normal World by directly accessing the physical address of the request buffer :
PINF("req_buf = %s (0x%x)", (char*)((struct smc_cmd*)cmd_addr)->req_buf_phys, ((struct smc_cmd*)cmd_addr)->req_buf_phys);
Ridiculously and Unfortunately, I’m in trouble to write some characters in response buffer (whose address is the physical address of Normal World). I used Genode::memcpy() to write the characters as follows where cmd_addr is the physical address of the command structure passed from Normal World :
/* acquire data to be written into memory space of normal world */ Genode::memcpy(tmp, (const char*) "From Secure World", strlen("From Secure World")); tmp[17] = '\0';
/* write a data into resp_buf_phys */ Genode::memcpy((char*)((struct smc_cmd*)cmd_addr)->resp_buf_phys, (const char*) tmp, sizeof(tmp));
/* printout contents of memory for debug */ PINF("res_buf = %s (0x%x)", (char*)((struct smc_cmd*)cmd_addr)->resp_buf_phys, ((struct smc_cmd*)cmd_addr)->resp_buf_phys);
It seems that the writing operation in Secure World is successful since the last PINF() shows me the “From Secure World” in console.
However, when I read the address (converted from the physical address using phys_to_virt()) in my device driver, I can only see the empty string (initial status).
My questions are :
Do I need another approach to write the physical memory of Normal World in the side of Genode? Is there any simple example or any volunteer to share an example for this kind of operation? Is there any comment to implement this kind of example?
Hello,
our trustzone experts are out of office for the next weeks (vacation).
Nevertheless, several questions similar to your issue has been already asked on the mailing list, please search for it in the archive [1]. E.g. Ofer Hasson addressed the same/similar issue and succeeded, according to this thread [0], with passing data between both worlds.
Cheers,
Alex.
[0] http://sourceforge.net/p/genode/mailman/message/34182558/ [1] http://sourceforge.net/p/genode/mailman/genode-main/
On 14.07.2015 11:00, JaeminPark wrote:
I’m currently developing a simple trustzone device driver running in Normal World to communicate with Genode in Secure World. I’m using IMX53 QSB, Genode 15.02 as Secure OS, and customized Linux as OS for Normal World.
In Normal World, my simple device driver calls smc instruction inside module_init(). The instruction is invoked with the command structure (named by “struct smc_cmd”). The physical address of "struct smc_cmd" is passing to Genode via _vm->state()->r1. There exists two physical addresses inside “struct smc_cmd": one for request buffer and the other for response buffer where the response buffer is allocated by kzalloc(). For the address conversion, I used virt_to_phys().
In Secure World (Genode), I’m modifying the tz_vmm source code for this experiment. I’m succeed in reading the request buffer from Normal World by directly accessing the physical address of the request buffer :
PINF("req_buf = %s (0x%x)", (char*)((struct smc_cmd*)cmd_addr)->req_buf_phys, ((struct smc_cmd*)cmd_addr)->req_buf_phys);
Ridiculously and Unfortunately, I’m in trouble to write some characters in response buffer (whose address is the physical address of Normal World). I used Genode::memcpy() to write the characters as follows where cmd_addr is the physical address of the command structure passed from Normal World :
/* acquire data to be written into memory space of normal world */ Genode::memcpy(tmp, (const char*) "From Secure World", strlen(">From Secure World")); tmp[17] = '\0';
/* write a data into resp_buf_phys */
Genode::memcpy((char*)((struct smc_cmd*)cmd_addr)->resp_buf_phys, (const char*) tmp, sizeof(tmp));
/* printout contents of memory for debug */ PINF("res_buf = %s (0x%x)", (char*)((struct smc_cmd*)cmd_addr)->resp_buf_phys, ((struct smc_cmd*)cmd_addr)->resp_buf_phys);
It seems that the writing operation in Secure World is successful since the last PINF() shows me the “From Secure World” in console.
However, when I read the address (converted from the physical address using phys_to_virt()) in my device driver, I can only see the empty string (initial status).
My questions are :
Do I need another approach to write the physical memory of Normal World in the side of Genode? Is there any simple example or any volunteer to share an example for this kind of operation? Is there any comment to implement this kind of example?
Don't Limit Your Business. Reach for the Cloud. GigeNET's Cloud Solutions provide you with the tools and support that you need to offload your IT needs and focus on growing your business. Configured For All Businesses. Start Your Cloud Today. https://www.gigenetcloud.com/
genode-main mailing list genode-main@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/genode-main
Hi Jaemin,
Without going deeper into your specific problem, I'd like to suggest you to have a look at my working branches [1] that concern with issue [2]. They show a working implementation of shared-mem communication between secure and non-secure world. The interesting parts in your case are:
* Mapping of the buffer in file [3] in line 422. Note that we create a pseudo-device struct for that in line 406. This struct isn't related to any real device and is merely needed because dma_alloc_coherent must know from which DMA pool to allocate with which parameters.
* Registration of the buffer in file [3] via function genblk_smc_buffer
* Secure to non-secure communication in file [3] in genblk_smc_name. Secure back-end in file [4] in Vm::smc_blk_name.
* Non-secure to secure communication in file [3] in genode_blk_request if argument write=true. Secure back-end in file [4] in Vm::smc_blk_submit the call to blk_buf_to_pkt.
Please be aware that - although it works on hardware - this code is still in progress and should not be considered as final solution. If you have further questions, don't hesitate to ask ;)
Cheers, Martin
[1] https://github.com/m-stein/genode/tree/1497_usb_armory_demo https://github.com/m-stein/linux/tree/1497_usb_armory_demo
[2] https://github.com/genodelabs/genode/issues/1497
[3] <LINUX>/drivers/block/genode_block.c
[4] <GENODE>/repos/os/src/server/tz_vmm/usb_armory/vm.h
On 14.07.2015 11:00, JaeminPark wrote:
I’m currently developing a simple trustzone device driver running in Normal World to communicate with Genode in Secure World. I’m using IMX53 QSB, Genode 15.02 as Secure OS, and customized Linux as OS for Normal World.
In Normal World, my simple device driver calls */smc/* instruction inside */module_init()/*. The instruction is invoked with the command structure (named by “*/struct smc_cmd/*”). The physical address of "struct smc_cmd" is passing to Genode via */_vm->state()->r1/*. There exists two physical addresses inside “struct smc_cmd": one for request buffer and the other for response buffer where the response buffer is allocated by */kzalloc()/*. For the address conversion, I used /*virt_to_phys()*/.
In Secure World (Genode), I’m modifying the */tz_vmm /*source code for this experiment. I’m succeed in reading the request buffer from Normal World by directly accessing the physical address of the request buffer :
*PINF("req_buf = %s (0x%x)", (char*)((struct smc_cmd*)cmd_addr)->req_buf_phys, ((struct smc_cmd*)cmd_addr)->req_buf_phys);*
Ridiculously and Unfortunately, I’m in trouble to write some characters in response buffer (whose address is the physical address of Normal World). I used */Genode::memcpy()/* to write the characters as follows where */cmd_addr/* is the physical address of the command structure passed from Normal World :
*//* acquire data to be written into memory space of normal world *//* */ Genode::memcpy(tmp, (const char*) "From Secure World", strlen("From Secure World"));/* */ tmp[17] = '\0';/* */ /* */ /* write a data into resp_buf_phys *//* */Genode::memcpy((char*)((struct smc_cmd*)cmd_addr)->resp_buf_phys, (const char*) tmp, sizeof(tmp));/* */ /* */ /* printout contents of memory for debug *//* */ PINF("res_buf = %s (0x%x)", (char*)((struct smc_cmd*)cmd_addr)->resp_buf_phys, ((struct smc_cmd*)cmd_addr)->resp_buf_phys);/*
It seems that the writing operation in Secure World is successful since the last PINF() shows me the “From Secure World” in console.
However, when I read the address (converted from the physical address using */phys_to_virt()/*) in my device driver, I can only see the empty string (initial status).
My questions are :
- Do I need another approach to write the physical memory of Normal World in the side of Genode?
- Is there any simple example or any volunteer to share an example for this kind of operation?
- Is there any comment to implement this kind of example?
Don't Limit Your Business. Reach for the Cloud. GigeNET's Cloud Solutions provide you with the tools and support that you need to offload your IT needs and focus on growing your business. Configured For All Businesses. Start Your Cloud Today. https://www.gigenetcloud.com/
genode-main mailing list genode-main@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/genode-main