LE site francophone de référence sur le Hack de vos PlayStations
L'intégrale des patchs True Blue JB2 / BR / 3.41 / 3.55
Chargement ...
[MAJ 2] Recherches et Avancées du Hack de la PS3...
Re: [MAJ 2] Recherches et Avancées du Hack de la PS3...
bon voila je peux vous confirmer que c fait apres quelque jours de test jai finalement reussi a dumper les loader et juste les loader du fw 4.0 a partir du cfw 3.55 special
comme vous voyer les loader sont successive
lv1ldr
lv2ldr
isoldr
appldr
et voici un dump du 3.55 qui differt totalement du 4.0
appldr
creserved_0
default.spp
emer init.self
eurusfw.bin
hdd copy.self
isoldr
lv0
lv1.self
lv1ldr
lv2ldr
ce qui me manque c comment les extraire je c que c simple mai je connais pas
comme vous voyer les loader sont successive
lv1ldr
lv2ldr
isoldr
appldr
et voici un dump du 3.55 qui differt totalement du 4.0
appldr
creserved_0
default.spp
emer init.self
eurusfw.bin
hdd copy.self
isoldr
lv0
lv1.self
lv1ldr
lv2ldr
ce qui me manque c comment les extraire je c que c simple mai je connais pas
- arisse2001
- Habitué
- Messages: 227
- Inscription: Sam 12 Fév 2011 20:54
Re: [MAJ 2] Recherches et Avancées du Hack de la PS3...
Arisse tu as le dump du LV0 et Metdlr du FW 4.00 original ?
-

Dr_Charlatan - Habitué
- Messages: 241
- Inscription: Ven 13 Aoû 2010 23:41
- Localisation: Paris
Re: [MAJ 2] Recherches et Avancées du Hack de la PS3...
dr la methode que jai c simple
jai demarrer mas ps3 en 4.0 mais jai mit le disk dur du 3.55 et juste apres quelque seconde que allez decouvrire vous meme puis jai changer en 3.55 en ce moment la les loader son copier ram du ps3 et la ps3 A demarrer en 3.55 PUIS puis jai dumper la ram A decouvrir vous meme comment
puis jai lancer la dump avec ida et jai chercher ldr et je les trouver
au debut jetait pas sur que ce sont les loader mais lorsque jai dumper laram en 3.55 et jai comparer cetait clair que sont les loader du fw 4.0
en suisvant ce qui c passer tout etait effacer sauf la partie ou les loader sont
jai aucune idée tout ce que jai c que cesi sont les loader
mais attander c pas tou faut un moyen de les extraire et pourcela faut demnder au gas qui as partager cette theori
qui est bien sur mathieulh
jai demarrer mas ps3 en 4.0 mais jai mit le disk dur du 3.55 et juste apres quelque seconde que allez decouvrire vous meme puis jai changer en 3.55 en ce moment la les loader son copier ram du ps3 et la ps3 A demarrer en 3.55 PUIS puis jai dumper la ram A decouvrir vous meme comment
puis jai lancer la dump avec ida et jai chercher ldr et je les trouver
au debut jetait pas sur que ce sont les loader mais lorsque jai dumper laram en 3.55 et jai comparer cetait clair que sont les loader du fw 4.0
en suisvant ce qui c passer tout etait effacer sauf la partie ou les loader sont
jai aucune idée tout ce que jai c que cesi sont les loader
mais attander c pas tou faut un moyen de les extraire et pourcela faut demnder au gas qui as partager cette theori
qui est bien sur mathieulh
- arisse2001
- Habitué
- Messages: 227
- Inscription: Sam 12 Fév 2011 20:54
Re: [MAJ 2] Recherches et Avancées du Hack de la PS3...
Tu as donc un .bin avec les loaders 4.00 dedans et en prime des entêtes ?
Je peux me charger d'isoler chaque loaders et de te les envoyer une fois extraits, je sais comment fonctionne les entêtes mais je ne sais pas vraiment l'expliquer
Je peux me charger d'isoler chaque loaders et de te les envoyer une fois extraits, je sais comment fonctionne les entêtes mais je ne sais pas vraiment l'expliquer

- raymanvtwo
- Expert
- Messages: 418
- Inscription: Dim 11 Sep 2011 16:31
Re: [MAJ 2] Recherches et Avancées du Hack de la PS3...
arisse2001 a écrit:bon voila je peux vous confirmer que c fait apres quelque jours de test jai finalement reussi a dumper les loader et juste les loader du fw 4.0 a partir du cfw 3.55 special
comme vous voyer les loader sont successive
lv1ldr
lv2ldr
isoldr
appldr
et voici un dump du 3.55 qui differt totalement du 4.0
appldr
creserved_0
default.spp
emer init.self
eurusfw.bin
hdd copy.self
isoldr
lv0
lv1.self
lv1ldr
lv2ldr
ce qui me manque c comment les extraire je c que c simple mai je connais pas
Ce ne sont pas les LOADERS mais juste une référence à eux ! En même temps ça saute au yeux... c'est plein de '00'
- Code: Tout sélectionner
6C 76 31 6C 64 72 00 00 00 00 00 00 00 00 00 00 --lv1ldr
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 05 EC 90 00 00 00 00 00 01 75 F8
6C 76 32 6C 64 72 00 00 00 00 00 00 00 00 00 00 --lv2ldr
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 07 62 90 00 00 00 00 00 01 2F 94
69 73 6F 6C 64 72 00 00 00 00 00 00 00 00 00 00 --isoldr
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 08 92 30 00 00 00 00 00 01 F6 08
61 70 70 6C 64 72 00 00 00 00 00 00 00 00 00 00 --appldr
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 0A 89 10 00 00 00 00 00 00 FB 4C
Mais selon toi, il s'agirait des loader du fw 4.0, sauf que dans IDA ta fenêtre se nomme C:\Users\users\20090101-045820-LV1-FW3.55.BIN
Encore une fois tes explications brouillons me laisse plus que perplexe et les seules preuves que tu avances sont des captures d'écran ...
- kill3r
- Addict
- Messages: 2249
- Inscription: Lun 21 Sep 2009 13:41
Re: [MAJ 2] Recherches et Avancées du Hack de la PS3...
oui par ce que ta pas un flasher tu c pas de koi je parle jais bien dit que c en 3.55 et jai bien que jais switcher entre les deux fw et jais bien dit que javais activer le dualboot mais au lieu de me critiquer fallait m'aider
moi des le debut jai bien dit que je ne connais pas trop sur le software et comment dumper mais c plus le cas hamdoulilah jai pris mon temp a apprendre comment la ps3 fonctionne jais acheter plusieurs console et plusieurs tool pour bien connaitre
je voulais pas poster par ce que plusieur entre vous von moquer de mes poste
je remercie frodo je remercie songo je remercie switch et je te remercie toi mon ami
et tou les ami qui ont croyer a moi
bon
a ce qui concerne ce que jai poster ici avant c inutile mais il ma aider au début

moi des le debut jai bien dit que je ne connais pas trop sur le software et comment dumper mais c plus le cas hamdoulilah jai pris mon temp a apprendre comment la ps3 fonctionne jais acheter plusieurs console et plusieurs tool pour bien connaitre
je voulais pas poster par ce que plusieur entre vous von moquer de mes poste
je remercie frodo je remercie songo je remercie switch et je te remercie toi mon ami
et tou les ami qui ont croyer a moi
bon
a ce qui concerne ce que jai poster ici avant c inutile mais il ma aider au début

- arisse2001
- Habitué
- Messages: 227
- Inscription: Sam 12 Fév 2011 20:54
Re: [MAJ 2] Recherches et Avancées du Hack de la PS3...
Pour le nom du fichier ça peut se comprendre ... mais croire que les loaders tiennent en quelques bytes ...
- kill3r
- Addict
- Messages: 2249
- Inscription: Lun 21 Sep 2009 13:41
Re: [MAJ 2] Recherches et Avancées du Hack de la PS3...
kill3r tu vois que ta pas compris ce que jai poster c unitule mais je te l explique
lorsque tu dump la ram du 3.55
et tu ouvre le dump avec ida et tu cherche les loaders
il vont être comme sa :
isoldr
lv0
lv1.self
lv1ldr
lv2ldr
mais lorsque tu as le dualboot et tu demmare ta ps3 en 4.0 et tu switch l e3 en 3.55 et tu dump la ram les loader vont etre comme sa :
lv1ldr
lv2ldr
isoldr
appldr
lorsque tu dump la ram du 3.55
et tu ouvre le dump avec ida et tu cherche les loaders
il vont être comme sa :
isoldr
lv0
lv1.self
lv1ldr
lv2ldr
mais lorsque tu as le dualboot et tu demmare ta ps3 en 4.0 et tu switch l e3 en 3.55 et tu dump la ram les loader vont etre comme sa :
lv1ldr
lv2ldr
isoldr
appldr
- arisse2001
- Habitué
- Messages: 227
- Inscription: Sam 12 Fév 2011 20:54
Re: [MAJ 2] Recherches et Avancées du Hack de la PS3...
javais trouver quelque chose avant qu'il ma pas intéresser mais je vais te le montrer et j'aimerai que tu m'aide a le comprendre la semaine prochaine inchaalah je ve te le poster ici 

- arisse2001
- Habitué
- Messages: 227
- Inscription: Sam 12 Fév 2011 20:54
Re: [MAJ 2] Recherches et Avancées du Hack de la PS3...
- Code: Tout sélectionner
* PS3 flash memory os area.
*
* Copyright (C) 2006 Sony Computer Entertainment Inc.
* Copyright 2006 Sony Corp.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/kernel.h>
#include <linux/io.h>
#include <linux/workqueue.h>
#include <linux/fs.h>
#include <linux/syscalls.h>
#include <asm/lmb.h>
#include "platform.h"
enum {
OS_AREA_SEGMENT_SIZE = 0X200,
};
enum os_area_ldr_format {
HEADER_LDR_FORMAT_RAW = 0,
HEADER_LDR_FORMAT_GZIP = 1,
};
/**
* struct os_area_header - os area header segment.
* @magic_num: Always 'cell_ext_os_area'.
* @hdr_version: Header format version number.
* @db_area_offset: Starting segment number of other os database area.
* @ldr_area_offset: Starting segment number of bootloader image area.
* @ldr_format: HEADER_LDR_FORMAT flag.
* @ldr_size: Size of bootloader image in bytes.
*
* Note that the docs refer to area offsets. These are offsets in units of
* segments from the start of the os area (top of the header). These are
* better thought of as segment numbers. The os area of the os area is
* reserved for the os image.
*/
struct os_area_header {
u8 magic_num[16];
u32 hdr_version;
u32 db_area_offset;
u32 ldr_area_offset;
u32 _reserved_1;
u32 ldr_format;
u32 ldr_size;
u32 _reserved_2[6];
};
enum os_area_boot_flag {
PARAM_BOOT_FLAG_GAME_OS = 0,
PARAM_BOOT_FLAG_OTHER_OS = 1,
};
enum os_area_ctrl_button {
PARAM_CTRL_BUTTON_O_IS_YES = 0,
PARAM_CTRL_BUTTON_X_IS_YES = 1,
};
/**
* struct os_area_params - os area params segment.
* @boot_flag: User preference of operating system, PARAM_BOOT_FLAG flag.
* @num_params: Number of params in this (params) segment.
* @rtc_diff: Difference in seconds between 1970 and the ps3 rtc value.
* @av_multi_out: User preference of AV output, PARAM_AV_MULTI_OUT flag.
* @ctrl_button: User preference of controller button config, PARAM_CTRL_BUTTON
* flag.
* @static_ip_addr: User preference of static IP address.
* @network_mask: User preference of static network mask.
* @default_gateway: User preference of static default gateway.
* @dns_primary: User preference of static primary dns server.
* @dns_secondary: User preference of static secondary dns server.
*
* The ps3 rtc maintains a read-only value that approximates seconds since
* 2000-01-01 00:00:00 UTC.
*
* User preference of zero for static_ip_addr means use dhcp.
*/
struct os_area_params {
u32 boot_flag;
u32 _reserved_1[3];
u32 num_params;
u32 _reserved_2[3];
/* param 0 */
s64 rtc_diff;
u8 av_multi_out;
u8 ctrl_button;
u8 _reserved_3[6];
/* param 1 */
u8 static_ip_addr[4];
u8 network_mask[4];
u8 default_gateway[4];
u8 _reserved_4[4];
/* param 2 */
u8 dns_primary[4];
u8 dns_secondary[4];
u8 _reserved_5[8];
};
enum {
OS_AREA_DB_MAGIC_NUM = 0x2d64622dU,
};
/**
* struct os_area_db - Shared flash memory database.
* @magic_num: Always '-db-' = 0x2d64622d.
* @version: os_area_db format version number.
* @index_64: byte offset of the database id index for 64 bit variables.
* @count_64: number of usable 64 bit index entries
* @index_32: byte offset of the database id index for 32 bit variables.
* @count_32: number of usable 32 bit index entries
* @index_16: byte offset of the database id index for 16 bit variables.
* @count_16: number of usable 16 bit index entries
*
* Flash rom storage for exclusive use by guests running in the other os lpar.
* The current system configuration allocates 1K (two segments) for other os
* use.
*/
struct os_area_db {
u32 magic_num;
u16 version;
u16 _reserved_1;
u16 index_64;
u16 count_64;
u16 index_32;
u16 count_32;
u16 index_16;
u16 count_16;
u32 _reserved_2;
u8 _db_data[1000];
};
/**
* enum os_area_db_owner - Data owners.
*/
enum os_area_db_owner {
OS_AREA_DB_OWNER_ANY = -1,
OS_AREA_DB_OWNER_NONE = 0,
OS_AREA_DB_OWNER_PROTOTYPE = 1,
OS_AREA_DB_OWNER_LINUX = 2,
OS_AREA_DB_OWNER_PETITBOOT = 3,
OS_AREA_DB_OWNER_MAX = 32,
};
enum os_area_db_key {
OS_AREA_DB_KEY_ANY = -1,
OS_AREA_DB_KEY_NONE = 0,
OS_AREA_DB_KEY_RTC_DIFF = 1,
OS_AREA_DB_KEY_VIDEO_MODE = 2,
OS_AREA_DB_KEY_MAX = 8,
};
struct os_area_db_id {
int owner;
int key;
};
static const struct os_area_db_id os_area_db_id_empty = {
.owner = OS_AREA_DB_OWNER_NONE,
.key = OS_AREA_DB_KEY_NONE
};
static const struct os_area_db_id os_area_db_id_any = {
.owner = OS_AREA_DB_OWNER_ANY,
.key = OS_AREA_DB_KEY_ANY
};
static const struct os_area_db_id os_area_db_id_rtc_diff = {
.owner = OS_AREA_DB_OWNER_LINUX,
.key = OS_AREA_DB_KEY_RTC_DIFF
};
static const struct os_area_db_id os_area_db_id_video_mode = {
.owner = OS_AREA_DB_OWNER_LINUX,
.key = OS_AREA_DB_KEY_VIDEO_MODE
};
#define SECONDS_FROM_1970_TO_2000 946684800LL
/**
* struct saved_params - Static working copies of data from the PS3 'os area'.
*
* The order of preference we use for the rtc_diff source:
* 1) The database value.
* 2) The game os value.
* 3) The number of seconds from 1970 to 2000.
*/
struct saved_params {
unsigned int valid;
s64 rtc_diff;
unsigned int av_multi_out;
} static saved_params;
static struct property property_rtc_diff = {
.name = "linux,rtc_diff",
.length = sizeof(saved_params.rtc_diff),
.value = &saved_params.rtc_diff,
};
static struct property property_av_multi_out = {
.name = "linux,av_multi_out",
.length = sizeof(saved_params.av_multi_out),
.value = &saved_params.av_multi_out,
};
/**
* os_area_set_property - Add or overwrite a saved_params value to the device tree.
*
* Overwrites an existing property.
*/
static void os_area_set_property(struct device_node *node,
struct property *prop)
{
int result;
struct property *tmp = of_find_property(node, prop->name, NULL);
if (tmp) {
pr_debug("%s:%d found %s\n", __func__, __LINE__, prop->name);
prom_remove_property(node, tmp);
}
result = prom_add_property(node, prop);
if (result)
pr_debug("%s:%d prom_set_property failed\n", __func__,
__LINE__);
}
/**
* os_area_get_property - Get a saved_params value from the device tree.
*
*/
static void __init os_area_get_property(struct device_node *node,
struct property *prop)
{
const struct property *tmp = of_find_property(node, prop->name, NULL);
if (tmp) {
BUG_ON(prop->length != tmp->length);
memcpy(prop->value, tmp->value, prop->length);
} else
pr_debug("%s:%d not found %s\n", __func__, __LINE__,
prop->name);
}
#define dump_header(_a) _dump_header(_a, __func__, __LINE__)
static void _dump_header(const struct os_area_header *h, const char *func,
int line)
{
pr_debug("%s:%d: h.magic_num: '%s'\n", func, line,
h->magic_num);
pr_debug("%s:%d: h.hdr_version: %u\n", func, line,
h->hdr_version);
pr_debug("%s:%d: h.db_area_offset: %u\n", func, line,
h->db_area_offset);
pr_debug("%s:%d: h.ldr_area_offset: %u\n", func, line,
h->ldr_area_offset);
pr_debug("%s:%d: h.ldr_format: %u\n", func, line,
h->ldr_format);
pr_debug("%s:%d: h.ldr_size: %xh\n", func, line,
h->ldr_size);
}
#define dump_params(_a) _dump_params(_a, __func__, __LINE__)
static void _dump_params(const struct os_area_params *p, const char *func,
int line)
{
pr_debug("%s:%d: p.boot_flag: %u\n", func, line, p->boot_flag);
pr_debug("%s:%d: p.num_params: %u\n", func, line, p->num_params);
pr_debug("%s:%d: p.rtc_diff %ld\n", func, line, p->rtc_diff);
pr_debug("%s:%d: p.av_multi_out %u\n", func, line, p->av_multi_out);
pr_debug("%s:%d: p.ctrl_button: %u\n", func, line, p->ctrl_button);
pr_debug("%s:%d: p.static_ip_addr: %u.%u.%u.%u\n", func, line,
p->static_ip_addr[0], p->static_ip_addr[1],
p->static_ip_addr[2], p->static_ip_addr[3]);
pr_debug("%s:%d: p.network_mask: %u.%u.%u.%u\n", func, line,
p->network_mask[0], p->network_mask[1],
p->network_mask[2], p->network_mask[3]);
pr_debug("%s:%d: p.default_gateway: %u.%u.%u.%u\n", func, line,
p->default_gateway[0], p->default_gateway[1],
p->default_gateway[2], p->default_gateway[3]);
pr_debug("%s:%d: p.dns_primary: %u.%u.%u.%u\n", func, line,
p->dns_primary[0], p->dns_primary[1],
p->dns_primary[2], p->dns_primary[3]);
pr_debug("%s:%d: p.dns_secondary: %u.%u.%u.%u\n", func, line,
p->dns_secondary[0], p->dns_secondary[1],
p->dns_secondary[2], p->dns_secondary[3]);
}
static int verify_header(const struct os_area_header *header)
{
if (memcmp(header->magic_num, "cell_ext_os_area", 16)) {
pr_debug("%s:%d magic_num failed\n", __func__, __LINE__);
return -1;
}
if (header->hdr_version < 1) {
pr_debug("%s:%d hdr_version failed\n", __func__, __LINE__);
return -1;
}
if (header->db_area_offset > header->ldr_area_offset) {
pr_debug("%s:%d offsets failed\n", __func__, __LINE__);
return -1;
}
return 0;
}
static int db_verify(const struct os_area_db *db)
{
if (db->magic_num != OS_AREA_DB_MAGIC_NUM) {
pr_debug("%s:%d magic_num failed\n", __func__, __LINE__);
return -1;
}
if (db->version != 1) {
pr_debug("%s:%d version failed\n", __func__, __LINE__);
return -1;
}
return 0;
}
struct db_index {
uint8_t owner:5;
uint8_t key:3;
};
struct db_iterator {
const struct os_area_db *db;
struct os_area_db_id match_id;
struct db_index *idx;
struct db_index *last_idx;
union {
uint64_t *value_64;
uint32_t *value_32;
uint16_t *value_16;
};
};
static unsigned int db_align_up(unsigned int val, unsigned int size)
{
return (val + (size - 1)) & (~(size - 1));
}
/**
* db_for_each_64 - Iterator for 64 bit entries.
*
* A NULL value for id can be used to match all entries.
* OS_AREA_DB_OWNER_ANY and OS_AREA_DB_KEY_ANY can be used to match all.
*/
static int db_for_each_64(const struct os_area_db *db,
const struct os_area_db_id *match_id, struct db_iterator *i)
{
next:
if (!i->db) {
i->db = db;
i->match_id = match_id ? *match_id : os_area_db_id_any;
i->idx = (void *)db + db->index_64;
i->last_idx = i->idx + db->count_64;
i->value_64 = (void *)db + db->index_64
+ db_align_up(db->count_64, 8);
} else {
i->idx++;
i->value_64++;
}
if (i->idx >= i->last_idx) {
pr_debug("%s:%d: reached end\n", __func__, __LINE__);
return 0;
}
if (i->match_id.owner != OS_AREA_DB_OWNER_ANY
&& i->match_id.owner != (int)i->idx->owner)
goto next;
if (i->match_id.key != OS_AREA_DB_KEY_ANY
&& i->match_id.key != (int)i->idx->key)
goto next;
return 1;
}
static int db_delete_64(struct os_area_db *db, const struct os_area_db_id *id)
{
struct db_iterator i;
for (i.db = NULL; db_for_each_64(db, id, &i); ) {
pr_debug("%s:%d: got (%d:%d) %llxh\n", __func__, __LINE__,
i.idx->owner, i.idx->key,
(unsigned long long)*i.value_64);
i.idx->owner = 0;
i.idx->key = 0;
*i.value_64 = 0;
}
return 0;
}
static int db_set_64(struct os_area_db *db, const struct os_area_db_id *id,
uint64_t value)
{
struct db_iterator i;
pr_debug("%s:%d: (%d:%d) <= %llxh\n", __func__, __LINE__,
id->owner, id->key, (unsigned long long)value);
if (!id->owner || id->owner == OS_AREA_DB_OWNER_ANY
|| id->key == OS_AREA_DB_KEY_ANY) {
pr_debug("%s:%d: bad id: (%d:%d)\n", __func__,
__LINE__, id->owner, id->key);
return -1;
}
db_delete_64(db, id);
i.db = NULL;
if (db_for_each_64(db, &os_area_db_id_empty, &i)) {
pr_debug("%s:%d: got (%d:%d) %llxh\n", __func__, __LINE__,
i.idx->owner, i.idx->key,
(unsigned long long)*i.value_64);
i.idx->owner = id->owner;
i.idx->key = id->key;
*i.value_64 = value;
pr_debug("%s:%d: set (%d:%d) <= %llxh\n", __func__, __LINE__,
i.idx->owner, i.idx->key,
(unsigned long long)*i.value_64);
return 0;
}
pr_debug("%s:%d: database full.\n",
__func__, __LINE__);
return -1;
}
static int db_get_64(const struct os_area_db *db,
const struct os_area_db_id *id, uint64_t *value)
{
struct db_iterator i;
i.db = NULL;
if (db_for_each_64(db, id, &i)) {
*value = *i.value_64;
pr_debug("%s:%d: found %lld\n", __func__, __LINE__,
(long long int)*i.value_64);
return 0;
}
pr_debug("%s:%d: not found\n", __func__, __LINE__);
return -1;
}
static int db_get_rtc_diff(const struct os_area_db *db, int64_t *rtc_diff)
{
return db_get_64(db, &os_area_db_id_rtc_diff, (uint64_t*)rtc_diff);
}
#define dump_db(a) _dump_db(a, __func__, __LINE__)
static void _dump_db(const struct os_area_db *db, const char *func,
int line)
{
pr_debug("%s:%d: db.magic_num: '%s'\n", func, line,
(const char*)&db->magic_num);
pr_debug("%s:%d: db.version: %u\n", func, line,
db->version);
pr_debug("%s:%d: db.index_64: %u\n", func, line,
db->index_64);
pr_debug("%s:%d: db.count_64: %u\n", func, line,
db->count_64);
pr_debug("%s:%d: db.index_32: %u\n", func, line,
db->index_32);
pr_debug("%s:%d: db.count_32: %u\n", func, line,
db->count_32);
pr_debug("%s:%d: db.index_16: %u\n", func, line,
db->index_16);
pr_debug("%s:%d: db.count_16: %u\n", func, line,
db->count_16);
}
static void os_area_db_init(struct os_area_db *db)
{
enum {
HEADER_SIZE = offsetof(struct os_area_db, _db_data),
INDEX_64_COUNT = 64,
VALUES_64_COUNT = 57,
INDEX_32_COUNT = 64,
VALUES_32_COUNT = 57,
INDEX_16_COUNT = 64,
VALUES_16_COUNT = 57,
};
memset(db, 0, sizeof(struct os_area_db));
db->magic_num = OS_AREA_DB_MAGIC_NUM;
db->version = 1;
db->index_64 = HEADER_SIZE;
db->count_64 = VALUES_64_COUNT;
db->index_32 = HEADER_SIZE
+ INDEX_64_COUNT * sizeof(struct db_index)
+ VALUES_64_COUNT * sizeof(u64);
db->count_32 = VALUES_32_COUNT;
db->index_16 = HEADER_SIZE
+ INDEX_64_COUNT * sizeof(struct db_index)
+ VALUES_64_COUNT * sizeof(u64)
+ INDEX_32_COUNT * sizeof(struct db_index)
+ VALUES_32_COUNT * sizeof(u32);
db->count_16 = VALUES_16_COUNT;
/* Rules to check db layout. */
BUILD_BUG_ON(sizeof(struct db_index) != 1);
BUILD_BUG_ON(sizeof(struct os_area_db) != 2 * OS_AREA_SEGMENT_SIZE);
BUILD_BUG_ON(INDEX_64_COUNT & 0x7);
BUILD_BUG_ON(VALUES_64_COUNT > INDEX_64_COUNT);
BUILD_BUG_ON(INDEX_32_COUNT & 0x7);
BUILD_BUG_ON(VALUES_32_COUNT > INDEX_32_COUNT);
BUILD_BUG_ON(INDEX_16_COUNT & 0x7);
BUILD_BUG_ON(VALUES_16_COUNT > INDEX_16_COUNT);
BUILD_BUG_ON(HEADER_SIZE
+ INDEX_64_COUNT * sizeof(struct db_index)
+ VALUES_64_COUNT * sizeof(u64)
+ INDEX_32_COUNT * sizeof(struct db_index)
+ VALUES_32_COUNT * sizeof(u32)
+ INDEX_16_COUNT * sizeof(struct db_index)
+ VALUES_16_COUNT * sizeof(u16)
> sizeof(struct os_area_db));
}
/**
* update_flash_db - Helper for os_area_queue_work_handler.
*
*/
static void update_flash_db(void)
{
int result;
int file;
off_t offset;
ssize_t count;
static const unsigned int buf_len = 8 * OS_AREA_SEGMENT_SIZE;
const struct os_area_header *header;
struct os_area_db* db;
/* Read in header and db from flash. */
file = sys_open("/dev/ps3flash", O_RDWR, 0);
if (file < 0) {
pr_debug("%s:%d sys_open failed\n", __func__, __LINE__);
goto fail_open;
}
header = kmalloc(buf_len, GFP_KERNEL);
if (!header) {
pr_debug("%s:%d kmalloc failed\n", __func__, __LINE__);
goto fail_malloc;
}
offset = sys_lseek(file, 0, SEEK_SET);
if (offset != 0) {
pr_debug("%s:%d sys_lseek failed\n", __func__, __LINE__);
goto fail_header_seek;
}
count = sys_read(file, (char __user *)header, buf_len);
result = count < OS_AREA_SEGMENT_SIZE || verify_header(header)
|| count < header->db_area_offset * OS_AREA_SEGMENT_SIZE;
if (result) {
pr_debug("%s:%d verify_header failed\n", __func__, __LINE__);
dump_header(header);
goto fail_header;
}
/* Now got a good db offset and some maybe good db data. */
db = (void*)header + header->db_area_offset * OS_AREA_SEGMENT_SIZE;
result = db_verify(db);
if (result) {
printk(KERN_NOTICE "%s:%d: Verify of flash database failed, "
"formatting.\n", __func__, __LINE__);
dump_db(db);
os_area_db_init(db);
}
/* Now got good db data. */
db_set_64(db, &os_area_db_id_rtc_diff, saved_params.rtc_diff);
offset = sys_lseek(file, header->db_area_offset * OS_AREA_SEGMENT_SIZE,
SEEK_SET);
if (offset != header->db_area_offset * OS_AREA_SEGMENT_SIZE) {
pr_debug("%s:%d sys_lseek failed\n", __func__, __LINE__);
goto fail_db_seek;
}
count = sys_write(file, (const char __user *)db,
sizeof(struct os_area_db));
if (count < sizeof(struct os_area_db)) {
pr_debug("%s:%d sys_write failed\n", __func__, __LINE__);
}
fail_db_seek:
fail_header:
fail_header_seek:
kfree(header);
fail_malloc:
sys_close(file);
fail_open:
return;
}
/**
* os_area_queue_work_handler - Asynchronous write handler.
*
* An asynchronous write for flash memory and the device tree. Do not
* call directly, use os_area_queue_work().
*/
static void os_area_queue_work_handler(struct work_struct *work)
{
struct device_node *node;
pr_debug(" -> %s:%d\n", __func__, __LINE__);
node = of_find_node_by_path("/");
if (node) {
os_area_set_property(node, &property_rtc_diff);
of_node_put(node);
} else
pr_debug("%s:%d of_find_node_by_path failed\n",
__func__, __LINE__);
#if defined(CONFIG_PS3_FLASH) || defined(CONFIG_PS3_FLASH_MODULE)
update_flash_db();
#else
printk(KERN_WARNING "%s:%d: No flash rom driver configured.\n",
__func__, __LINE__);
#endif
pr_debug(" <- %s:%d\n", __func__, __LINE__);
}
static void os_area_queue_work(void)
{
static DECLARE_WORK(q, os_area_queue_work_handler);
wmb();
schedule_work(&q);
}
/**
* ps3_os_area_save_params - Copy data from os area mirror to @saved_params.
*
* For the convenience of the guest the HV makes a copy of the os area in
* flash to a high address in the boot memory region and then puts that RAM
* address and the byte count into the repository for retrieval by the guest.
* We copy the data we want into a static variable and allow the memory setup
* by the HV to be claimed by the lmb manager.
*
* The os area mirror will not be available to a second stage kernel, and
* the header verify will fail. In this case, the saved_params values will
* be set from flash memory or the passed in device tree in ps3_os_area_init().
*/
void __init ps3_os_area_save_params(void)
{
int result;
u64 lpar_addr;
unsigned int size;
struct os_area_header *header;
struct os_area_params *params;
struct os_area_db *db;
pr_debug(" -> %s:%d\n", __func__, __LINE__);
result = ps3_repository_read_boot_dat_info(&lpar_addr, &size);
if (result) {
pr_debug("%s:%d ps3_repository_read_boot_dat_info failed\n",
__func__, __LINE__);
return;
}
header = (struct os_area_header *)__va(lpar_addr);
params = (struct os_area_params *)__va(lpar_addr
+ OS_AREA_SEGMENT_SIZE);
result = verify_header(header);
if (result) {
/* Second stage kernels exit here. */
pr_debug("%s:%d verify_header failed\n", __func__, __LINE__);
dump_header(header);
return;
}
db = (struct os_area_db *)__va(lpar_addr
+ header->db_area_offset * OS_AREA_SEGMENT_SIZE);
dump_header(header);
dump_params(params);
dump_db(db);
result = db_verify(db) || db_get_rtc_diff(db, &saved_params.rtc_diff);
if (result)
saved_params.rtc_diff = params->rtc_diff ? params->rtc_diff
: SECONDS_FROM_1970_TO_2000;
saved_params.av_multi_out = params->av_multi_out;
saved_params.valid = 1;
memset(header, 0, sizeof(*header));
pr_debug(" <- %s:%d\n", __func__, __LINE__);
}
/**
* ps3_os_area_init - Setup os area device tree properties as needed.
*/
void __init ps3_os_area_init(void)
{
struct device_node *node;
pr_debug(" -> %s:%d\n", __func__, __LINE__);
node = of_find_node_by_path("/");
if (!saved_params.valid && node) {
/* Second stage kernels should have a dt entry. */
os_area_get_property(node, &property_rtc_diff);
os_area_get_property(node, &property_av_multi_out);
}
if(!saved_params.rtc_diff)
saved_params.rtc_diff = SECONDS_FROM_1970_TO_2000;
if (node) {
os_area_set_property(node, &property_rtc_diff);
os_area_set_property(node, &property_av_multi_out);
of_node_put(node);
} else
pr_debug("%s:%d of_find_node_by_path failed\n",
__func__, __LINE__);
pr_debug(" <- %s:%d\n", __func__, __LINE__);
}
/**
* ps3_os_area_get_rtc_diff - Returns the rtc diff value.
*/
u64 ps3_os_area_get_rtc_diff(void)
{
return saved_params.rtc_diff;
}
/**
* ps3_os_area_set_rtc_diff - Set the rtc diff value.
*
* An asynchronous write is needed to support writing updates from
* the timer interrupt context.
*/
void ps3_os_area_set_rtc_diff(u64 rtc_diff)
{
if (saved_params.rtc_diff != rtc_diff) {
saved_params.rtc_diff = rtc_diff;
os_area_queue_work();
}
}
/**
* ps3_os_area_get_av_multi_out - Returns the default video mode.
*/
enum ps3_param_av_multi_out ps3_os_area_get_av_multi_out(void)
{
return saved_params.av_multi_out;
}
EXPORT_SYMBOL_GPL(ps3_os_area_get_av_multi_out);
Dernière édition par arisse2001 le Dim 1 Avr 2012 23:55, édité 2 fois.
- arisse2001
- Habitué
- Messages: 227
- Inscription: Sam 12 Fév 2011 20:54
Re: [MAJ 2] Recherches et Avancées du Hack de la PS3...
- Code: Tout sélectionner
/*
2 * PS3 interrupt routines.
3 *
4 * Copyright (C) 2006 Sony Computer Entertainment Inc.
5 * Copyright 2006 Sony Corp.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include <linux/kernel.h>
22 #include <linux/module.h>
23 #include <linux/irq.h>
24
25 #include <asm/machdep.h>
26 #include <asm/udbg.h>
27 #include <asm/lv1call.h>
28 #include <asm/smp.h>
29
30 #include "platform.h"
31
32 #if defined(DEBUG)
33 #define DBG udbg_printf
34 #else
35 #define DBG pr_debug
36 #endif
37
38 /**
39 * struct ps3_bmp - a per cpu irq status and mask bitmap structure
40 * @status: 256 bit status bitmap indexed by plug
41 * @unused_1:
42 * @mask: 256 bit mask bitmap indexed by plug
43 * @unused_2:
44 * @lock:
45 * @ipi_debug_brk_mask:
46 *
47 * The HV mantains per SMT thread mappings of HV outlet to HV plug on
48 * behalf of the guest. These mappings are implemented as 256 bit guest
49 * supplied bitmaps indexed by plug number. The addresses of the bitmaps
50 * are registered with the HV through lv1_configure_irq_state_bitmap().
51 * The HV requires that the 512 bits of status + mask not cross a page
52 * boundary. PS3_BMP_MINALIGN is used to define this minimal 64 byte
53 * alignment.
54 *
55 * The HV supports 256 plugs per thread, assigned as {0..255}, for a total
56 * of 512 plugs supported on a processor. To simplify the logic this
57 * implementation equates HV plug value to Linux virq value, constrains each
58 * interrupt to have a system wide unique plug number, and limits the range
59 * of the plug values to map into the first dword of the bitmaps. This
60 * gives a usable range of plug values of {NUM_ISA_INTERRUPTS..63}. Note
61 * that there is no constraint on how many in this set an individual thread
62 * can acquire.
63 */
64
65 #define PS3_BMP_MINALIGN 64
66
67 struct ps3_bmp {
68 struct {
69 u64 status;
70 u64 unused_1[3];
71 u64 mask;
72 u64 unused_2[3];
73 };
74 u64 ipi_debug_brk_mask;
75 spinlock_t lock;
76 };
77
78 /**
79 * struct ps3_private - a per cpu data structure
80 * @bmp: ps3_bmp structure
81 * @ppe_id: HV logical_ppe_id
82 * @thread_id: HV thread_id
83 */
84
85 struct ps3_private {
86 struct ps3_bmp bmp __attribute__ ((aligned (PS3_BMP_MINALIGN)));
87 u64 ppe_id;
88 u64 thread_id;
89 };
90
91 static DEFINE_PER_CPU(struct ps3_private, ps3_private);
92
93 /**
94 * ps3_chip_mask - Set an interrupt mask bit in ps3_bmp.
95 * @virq: The assigned Linux virq.
96 *
97 * Sets ps3_bmp.mask and calls lv1_did_update_interrupt_mask().
98 */
99
100 static void ps3_chip_mask(unsigned int virq)
101 {
102 struct ps3_private *pd = get_irq_chip_data(virq);
103 unsigned long flags;
104
105 pr_debug("%s:%d: thread_id %lu, virq %d\n", __func__, __LINE__,
106 pd->thread_id, virq);
107
108 local_irq_save(flags);
109 clear_bit(63 - virq, &pd->bmp.mask);
110 lv1_did_update_interrupt_mask(pd->ppe_id, pd->thread_id);
111 local_irq_restore(flags);
112 }
113
114 /**
115 * ps3_chip_unmask - Clear an interrupt mask bit in ps3_bmp.
116 * @virq: The assigned Linux virq.
117 *
118 * Clears ps3_bmp.mask and calls lv1_did_update_interrupt_mask().
119 */
120
121 static void ps3_chip_unmask(unsigned int virq)
122 {
123 struct ps3_private *pd = get_irq_chip_data(virq);
124 unsigned long flags;
125
126 pr_debug("%s:%d: thread_id %lu, virq %d\n", __func__, __LINE__,
127 pd->thread_id, virq);
128
129 local_irq_save(flags);
130 set_bit(63 - virq, &pd->bmp.mask);
131 lv1_did_update_interrupt_mask(pd->ppe_id, pd->thread_id);
132 local_irq_restore(flags);
133 }
134
135 /**
136 * ps3_chip_eoi - HV end-of-interrupt.
137 * @virq: The assigned Linux virq.
138 *
139 * Calls lv1_end_of_interrupt_ext().
140 */
141
142 static void ps3_chip_eoi(unsigned int virq)
143 {
144 const struct ps3_private *pd = get_irq_chip_data(virq);
145 lv1_end_of_interrupt_ext(pd->ppe_id, pd->thread_id, virq);
146 }
147
148 /**
149 * ps3_irq_chip - Represents the ps3_bmp as a Linux struct irq_chip.
150 */
151
152 static struct irq_chip ps3_irq_chip = {
153 .typename = "ps3",
154 .mask = ps3_chip_mask,
155 .unmask = ps3_chip_unmask,
156 .eoi = ps3_chip_eoi,
157 };
158
159 /**
160 * ps3_virq_setup - virq related setup.
161 * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
162 * serviced on.
163 * @outlet: The HV outlet from the various create outlet routines.
164 * @virq: The assigned Linux virq.
165 *
166 * Calls irq_create_mapping() to get a virq and sets the chip data to
167 * ps3_private data.
168 */
169
170 int ps3_virq_setup(enum ps3_cpu_binding cpu, unsigned long outlet,
171 unsigned int *virq)
172 {
173 int result;
174 struct ps3_private *pd;
175
176 /* This defines the default interrupt distribution policy. */
177
178 if (cpu == PS3_BINDING_CPU_ANY)
179 cpu = 0;
180
181 pd = &per_cpu(ps3_private, cpu);
182
183 *virq = irq_create_mapping(NULL, outlet);
184
185 if (*virq == NO_IRQ) {
186 pr_debug("%s:%d: irq_create_mapping failed: outlet %lu\n",
187 __func__, __LINE__, outlet);
188 result = -ENOMEM;
189 goto fail_create;
190 }
191
192 pr_debug("%s:%d: outlet %lu => cpu %u, virq %u\n", __func__, __LINE__,
193 outlet, cpu, *virq);
194
195 result = set_irq_chip_data(*virq, pd);
196
197 if (result) {
198 pr_debug("%s:%d: set_irq_chip_data failed\n",
199 __func__, __LINE__);
200 goto fail_set;
201 }
202
203 ps3_chip_mask(*virq);
204
205 return result;
206
207 fail_set:
208 irq_dispose_mapping(*virq);
209 fail_create:
210 return result;
211 }
212
213 /**
214 * ps3_virq_destroy - virq related teardown.
215 * @virq: The assigned Linux virq.
216 *
217 * Clears chip data and calls irq_dispose_mapping() for the virq.
218 */
219
220 int ps3_virq_destroy(unsigned int virq)
221 {
222 const struct ps3_private *pd = get_irq_chip_data(virq);
223
224 pr_debug("%s:%d: ppe_id %lu, thread_id %lu, virq %u\n", __func__,
225 __LINE__, pd->ppe_id, pd->thread_id, virq);
226
227 set_irq_chip_data(virq, NULL);
228 irq_dispose_mapping(virq);
229
230 pr_debug("%s:%d <-\n", __func__, __LINE__);
231 return 0;
232 }
233
234 /**
235 * ps3_irq_plug_setup - Generic outlet and virq related setup.
236 * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
237 * serviced on.
238 * @outlet: The HV outlet from the various create outlet routines.
239 * @virq: The assigned Linux virq.
240 *
241 * Sets up virq and connects the irq plug.
242 */
243
244 int ps3_irq_plug_setup(enum ps3_cpu_binding cpu, unsigned long outlet,
245 unsigned int *virq)
246 {
247 int result;
248 struct ps3_private *pd;
249
250 result = ps3_virq_setup(cpu, outlet, virq);
251
252 if (result) {
253 pr_debug("%s:%d: ps3_virq_setup failed\n", __func__, __LINE__);
254 goto fail_setup;
255 }
256
257 pd = get_irq_chip_data(*virq);
258
259 /* Binds outlet to cpu + virq. */
260
261 result = lv1_connect_irq_plug_ext(pd->ppe_id, pd->thread_id, *virq,
262 outlet, 0);
263
264 if (result) {
265 pr_info("%s:%d: lv1_connect_irq_plug_ext failed: %s\n",
266 __func__, __LINE__, ps3_result(result));
267 result = -EPERM;
268 goto fail_connect;
269 }
270
271 return result;
272
273 fail_connect:
274 ps3_virq_destroy(*virq);
275 fail_setup:
276 return result;
277 }
278 EXPORT_SYMBOL_GPL(ps3_irq_plug_setup);
279
280 /**
281 * ps3_irq_plug_destroy - Generic outlet and virq related teardown.
282 * @virq: The assigned Linux virq.
283 *
284 * Disconnects the irq plug and tears down virq.
285 * Do not call for system bus event interrupts setup with
286 * ps3_sb_event_receive_port_setup().
287 */
288
289 int ps3_irq_plug_destroy(unsigned int virq)
290 {
291 int result;
292 const struct ps3_private *pd = get_irq_chip_data(virq);
293
294 pr_debug("%s:%d: ppe_id %lu, thread_id %lu, virq %u\n", __func__,
295 __LINE__, pd->ppe_id, pd->thread_id, virq);
296
297 ps3_chip_mask(virq);
298
299 result = lv1_disconnect_irq_plug_ext(pd->ppe_id, pd->thread_id, virq);
300
301 if (result)
302 pr_info("%s:%d: lv1_disconnect_irq_plug_ext failed: %s\n",
303 __func__, __LINE__, ps3_result(result));
304
305 ps3_virq_destroy(virq);
306
307 return result;
308 }
309 EXPORT_SYMBOL_GPL(ps3_irq_plug_destroy);
310
311 /**
312 * ps3_event_receive_port_setup - Setup an event receive port.
313 * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
314 * serviced on.
315 * @virq: The assigned Linux virq.
316 *
317 * The virq can be used with lv1_connect_interrupt_event_receive_port() to
318 * arrange to receive interrupts from system-bus devices, or with
319 * ps3_send_event_locally() to signal events.
320 */
321
322 int ps3_event_receive_port_setup(enum ps3_cpu_binding cpu, unsigned int *virq)
323 {
324 int result;
325 unsigned long outlet;
326
327 result = lv1_construct_event_receive_port(&outlet);
328
329 if (result) {
330 pr_debug("%s:%d: lv1_construct_event_receive_port failed: %s\n",
331 __func__, __LINE__, ps3_result(result));
332 *virq = NO_IRQ;
333 return result;
334 }
335
336 result = ps3_irq_plug_setup(cpu, outlet, virq);
337 BUG_ON(result);
338
339 return result;
340 }
341 EXPORT_SYMBOL_GPL(ps3_event_receive_port_setup);
342
343 /**
344 * ps3_event_receive_port_destroy - Destroy an event receive port.
345 * @virq: The assigned Linux virq.
346 *
347 * Since ps3_event_receive_port_destroy destroys the receive port outlet,
348 * SB devices need to call disconnect_interrupt_event_receive_port() before
349 * this.
350 */
351
352 int ps3_event_receive_port_destroy(unsigned int virq)
353 {
354 int result;
355
356 pr_debug(" -> %s:%d virq %u\n", __func__, __LINE__, virq);
357
358 ps3_chip_mask(virq);
359
360 result = lv1_destruct_event_receive_port(virq_to_hw(virq));
361
362 if (result)
363 pr_debug("%s:%d: lv1_destruct_event_receive_port failed: %s\n",
364 __func__, __LINE__, ps3_result(result));
365
366 /*
367 * Don't call ps3_virq_destroy() here since ps3_smp_cleanup_cpu()
368 * calls from interrupt context (smp_call_function) when kexecing.
369 */
370
371 pr_debug(" <- %s:%d\n", __func__, __LINE__);
372 return result;
373 }
374
375 int ps3_send_event_locally(unsigned int virq)
376 {
377 return lv1_send_event_locally(virq_to_hw(virq));
378 }
379
380 /**
381 * ps3_sb_event_receive_port_setup - Setup a system bus event receive port.
382 * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
383 * serviced on.
384 * @dev: The system bus device instance.
385 * @virq: The assigned Linux virq.
386 *
387 * An event irq represents a virtual device interrupt. The interrupt_id
388 * coresponds to the software interrupt number.
389 */
390
391 int ps3_sb_event_receive_port_setup(struct ps3_system_bus_device *dev,
392 enum ps3_cpu_binding cpu, unsigned int *virq)
393 {
394 /* this should go in system-bus.c */
395
396 int result;
397
398 result = ps3_event_receive_port_setup(cpu, virq);
399
400 if (result)
401 return result;
402
403 result = lv1_connect_interrupt_event_receive_port(dev->bus_id,
404 dev->dev_id, virq_to_hw(*virq), dev->interrupt_id);
405
406 if (result) {
407 pr_debug("%s:%d: lv1_connect_interrupt_event_receive_port"
408 " failed: %s\n", __func__, __LINE__,
409 ps3_result(result));
410 ps3_event_receive_port_destroy(*virq);
411 *virq = NO_IRQ;
412 return result;
413 }
414
415 pr_debug("%s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__,
416 dev->interrupt_id, *virq);
417
418 return 0;
419 }
420 EXPORT_SYMBOL(ps3_sb_event_receive_port_setup);
421
422 int ps3_sb_event_receive_port_destroy(struct ps3_system_bus_device *dev,
423 unsigned int virq)
424 {
425 /* this should go in system-bus.c */
426
427 int result;
428
429 pr_debug(" -> %s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__,
430 dev->interrupt_id, virq);
431
432 result = lv1_disconnect_interrupt_event_receive_port(dev->bus_id,
433 dev->dev_id, virq_to_hw(virq), dev->interrupt_id);
434
435 if (result)
436 pr_debug("%s:%d: lv1_disconnect_interrupt_event_receive_port"
437 " failed: %s\n", __func__, __LINE__,
438 ps3_result(result));
439
440 result = ps3_event_receive_port_destroy(virq);
441 BUG_ON(result);
442
443 /*
444 * ps3_event_receive_port_destroy() destroys the IRQ plug,
445 * so don't call ps3_irq_plug_destroy() here.
446 */
447
448 result = ps3_virq_destroy(virq);
449 BUG_ON(result);
450
451 pr_debug(" <- %s:%d\n", __func__, __LINE__);
452 return result;
453 }
454 EXPORT_SYMBOL(ps3_sb_event_receive_port_destroy);
455
456 /**
457 * ps3_io_irq_setup - Setup a system bus io irq.
458 * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
459 * serviced on.
460 * @interrupt_id: The device interrupt id read from the system repository.
461 * @virq: The assigned Linux virq.
462 *
463 * An io irq represents a non-virtualized device interrupt. interrupt_id
464 * coresponds to the interrupt number of the interrupt controller.
465 */
466
467 int ps3_io_irq_setup(enum ps3_cpu_binding cpu, unsigned int interrupt_id,
468 unsigned int *virq)
469 {
470 int result;
471 unsigned long outlet;
472
473 result = lv1_construct_io_irq_outlet(interrupt_id, &outlet);
474
475 if (result) {
476 pr_debug("%s:%d: lv1_construct_io_irq_outlet failed: %s\n",
477 __func__, __LINE__, ps3_result(result));
478 return result;
479 }
480
481 result = ps3_irq_plug_setup(cpu, outlet, virq);
482 BUG_ON(result);
483
484 return result;
485 }
486 EXPORT_SYMBOL_GPL(ps3_io_irq_setup);
487
488 int ps3_io_irq_destroy(unsigned int virq)
489 {
490 int result;
491 unsigned long outlet = virq_to_hw(virq);
492
493 ps3_chip_mask(virq);
494
495 /*
496 * lv1_destruct_io_irq_outlet() will destroy the IRQ plug,
497 * so call ps3_irq_plug_destroy() first.
498 */
499
500 result = ps3_irq_plug_destroy(virq);
501 BUG_ON(result);
502
503 result = lv1_destruct_io_irq_outlet(outlet);
504
505 if (result)
506 pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n",
507 __func__, __LINE__, ps3_result(result));
508
509 return result;
510 }
511 EXPORT_SYMBOL_GPL(ps3_io_irq_destroy);
512
513 /**
514 * ps3_vuart_irq_setup - Setup the system virtual uart virq.
515 * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
516 * serviced on.
517 * @virt_addr_bmp: The caller supplied virtual uart interrupt bitmap.
518 * @virq: The assigned Linux virq.
519 *
520 * The system supports only a single virtual uart, so multiple calls without
521 * freeing the interrupt will return a wrong state error.
522 */
523
524 int ps3_vuart_irq_setup(enum ps3_cpu_binding cpu, void* virt_addr_bmp,
525 unsigned int *virq)
526 {
527 int result;
528 unsigned long outlet;
529 u64 lpar_addr;
530
531 BUG_ON(!is_kernel_addr((u64)virt_addr_bmp));
532
533 lpar_addr = ps3_mm_phys_to_lpar(__pa(virt_addr_bmp));
534
535 result = lv1_configure_virtual_uart_irq(lpar_addr, &outlet);
536
537 if (result) {
538 pr_debug("%s:%d: lv1_configure_virtual_uart_irq failed: %s\n",
539 __func__, __LINE__, ps3_result(result));
540 return result;
541 }
542
543 result = ps3_irq_plug_setup(cpu, outlet, virq);
544 BUG_ON(result);
545
546 return result;
547 }
548 EXPORT_SYMBOL_GPL(ps3_vuart_irq_setup);
549
550 int ps3_vuart_irq_destroy(unsigned int virq)
551 {
552 int result;
553
554 ps3_chip_mask(virq);
555 result = lv1_deconfigure_virtual_uart_irq();
556
557 if (result) {
558 pr_debug("%s:%d: lv1_configure_virtual_uart_irq failed: %s\n",
559 __func__, __LINE__, ps3_result(result));
560 return result;
561 }
562
563 result = ps3_irq_plug_destroy(virq);
564 BUG_ON(result);
565
566 return result;
567 }
568 EXPORT_SYMBOL_GPL(ps3_vuart_irq_destroy);
569
570 /**
571 * ps3_spe_irq_setup - Setup an spe virq.
572 * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
573 * serviced on.
574 * @spe_id: The spe_id returned from lv1_construct_logical_spe().
575 * @class: The spe interrupt class {0,1,2}.
576 * @virq: The assigned Linux virq.
577 *
578 */
579
580 int ps3_spe_irq_setup(enum ps3_cpu_binding cpu, unsigned long spe_id,
581 unsigned int class, unsigned int *virq)
582 {
583 int result;
584 unsigned long outlet;
585
586 BUG_ON(class > 2);
587
588 result = lv1_get_spe_irq_outlet(spe_id, class, &outlet);
589
590 if (result) {
591 pr_debug("%s:%d: lv1_get_spe_irq_outlet failed: %s\n",
592 __func__, __LINE__, ps3_result(result));
593 return result;
594 }
595
596 result = ps3_irq_plug_setup(cpu, outlet, virq);
597 BUG_ON(result);
598
599 return result;
600 }
601
602 int ps3_spe_irq_destroy(unsigned int virq)
603 {
604 int result;
605
606 ps3_chip_mask(virq);
607
608 result = ps3_irq_plug_destroy(virq);
609 BUG_ON(result);
610
611 return result;
612 }
613
614
615 #define PS3_INVALID_OUTLET ((irq_hw_number_t)-1)
616 #define PS3_PLUG_MAX 63
617
618 #if defined(DEBUG)
619 static void _dump_64_bmp(const char *header, const u64 *p, unsigned cpu,
620 const char* func, int line)
621 {
622 pr_debug("%s:%d: %s %u {%04lx_%04lx_%04lx_%04lx}\n",
623 func, line, header, cpu,
624 *p >> 48, (*p >> 32) & 0xffff, (*p >> 16) & 0xffff,
625 *p & 0xffff);
626 }
627
628 static void __maybe_unused _dump_256_bmp(const char *header,
629 const u64 *p, unsigned cpu, const char* func, int line)
630 {
631 pr_debug("%s:%d: %s %u {%016lx:%016lx:%016lx:%016lx}\n",
632 func, line, header, cpu, p[0], p[1], p[2], p[3]);
633 }
634
635 #define dump_bmp(_x) _dump_bmp(_x, __func__, __LINE__)
636 static void _dump_bmp(struct ps3_private* pd, const char* func, int line)
637 {
638 unsigned long flags;
639
640 spin_lock_irqsave(&pd->bmp.lock, flags);
641 _dump_64_bmp("stat", &pd->bmp.status, pd->thread_id, func, line);
642 _dump_64_bmp("mask", &pd->bmp.mask, pd->thread_id, func, line);
643 spin_unlock_irqrestore(&pd->bmp.lock, flags);
644 }
645
646 #define dump_mask(_x) _dump_mask(_x, __func__, __LINE__)
647 static void __maybe_unused _dump_mask(struct ps3_private *pd,
648 const char* func, int line)
649 {
650 unsigned long flags;
651
652 spin_lock_irqsave(&pd->bmp.lock, flags);
653 _dump_64_bmp("mask", &pd->bmp.mask, pd->thread_id, func, line);
654 spin_unlock_irqrestore(&pd->bmp.lock, flags);
655 }
656 #else
657 static void dump_bmp(struct ps3_private* pd) {};
658 #endif /* defined(DEBUG) */
659
660 static void ps3_host_unmap(struct irq_host *h, unsigned int virq)
661 {
662 set_irq_chip_data(virq, NULL);
663 }
664
665 static int ps3_host_map(struct irq_host *h, unsigned int virq,
666 irq_hw_number_t hwirq)
667 {
668 pr_debug("%s:%d: hwirq %lu, virq %u\n", __func__, __LINE__, hwirq,
669 virq);
670
671 set_irq_chip_and_handler(virq, &ps3_irq_chip, handle_fasteoi_irq);
672
673 return 0;
674 }
675
676 static int ps3_host_match(struct irq_host *h, struct device_node *np)
677 {
678 /* Match all */
679 return 1;
680 }
681
682 static struct irq_host_ops ps3_host_ops = {
683 .map = ps3_host_map,
684 .unmap = ps3_host_unmap,
685 .match = ps3_host_match,
686 };
687
688 void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq)
689 {
690 struct ps3_private *pd = &per_cpu(ps3_private, cpu);
691
692 pd->bmp.ipi_debug_brk_mask = 0x8000000000000000UL >> virq;
693
694 pr_debug("%s:%d: cpu %u, virq %u, mask %lxh\n", __func__, __LINE__,
695 cpu, virq, pd->bmp.ipi_debug_brk_mask);
696 }
697
698 static unsigned int ps3_get_irq(void)
699 {
700 struct ps3_private *pd = &__get_cpu_var(ps3_private);
701 u64 x = (pd->bmp.status & pd->bmp.mask);
702 unsigned int plug;
703
704 /* check for ipi break first to stop this cpu ASAP */
705
706 if (x & pd->bmp.ipi_debug_brk_mask)
707 x &= pd->bmp.ipi_debug_brk_mask;
708
709 asm volatile("cntlzd %0,%1" : "=r" (plug) : "r" (x));
710 plug &= 0x3f;
711
712 if (unlikely(plug) == NO_IRQ) {
713 pr_debug("%s:%d: no plug found: thread_id %lu\n", __func__,
714 __LINE__, pd->thread_id);
715 dump_bmp(&per_cpu(ps3_private, 0));
716 dump_bmp(&per_cpu(ps3_private, 1));
717 return NO_IRQ;
718 }
719
720 #if defined(DEBUG)
721 if (unlikely(plug < NUM_ISA_INTERRUPTS || plug > PS3_PLUG_MAX)) {
722 dump_bmp(&per_cpu(ps3_private, 0));
723 dump_bmp(&per_cpu(ps3_private, 1));
724 BUG();
725 }
726 #endif
727 return plug;
728 }
729
730 void __init ps3_init_IRQ(void)
731 {
732 int result;
733 unsigned cpu;
734 struct irq_host *host;
735
736 host = irq_alloc_host(NULL, IRQ_HOST_MAP_NOMAP, 0, &ps3_host_ops,
737 PS3_INVALID_OUTLET);
738 irq_set_default_host(host);
739 irq_set_virq_count(PS3_PLUG_MAX + 1);
740
741 for_each_possible_cpu(cpu) {
742 struct ps3_private *pd = &per_cpu(ps3_private, cpu);
743
744 lv1_get_logical_ppe_id(&pd->ppe_id);
745 pd->thread_id = get_hard_smp_processor_id(cpu);
746 spin_lock_init(&pd->bmp.lock);
747
748 pr_debug("%s:%d: ppe_id %lu, thread_id %lu, bmp %lxh\n",
749 __func__, __LINE__, pd->ppe_id, pd->thread_id,
750 ps3_mm_phys_to_lpar(__pa(&pd->bmp)));
751
752 result = lv1_configure_irq_state_bitmap(pd->ppe_id,
753 pd->thread_id, ps3_mm_phys_to_lpar(__pa(&pd->bmp)));
754
755 if (result)
756 pr_debug("%s:%d: lv1_configure_irq_state_bitmap failed:"
757 " %s\n", __func__, __LINE__,
758 ps3_result(result));
759 }
760
761 ppc_md.get_irq = ps3_get_irq;
762 }
763
764 void ps3_shutdown_IRQ(int cpu)
765 {
766 int result;
767 u64 ppe_id;
768 u64 thread_id = get_hard_smp_processor_id(cpu);
769
770 lv1_get_logical_ppe_id(&ppe_id);
771 result = lv1_configure_irq_state_bitmap(ppe_id, thread_id, 0);
772
773 DBG("%s:%d: lv1_configure_irq_state_bitmap (%lu:%lu/%d) %s\n", __func__,
774 __LINE__, ppe_id, thread_id, cpu, ps3_result(result));
775 }
- arisse2001
- Habitué
- Messages: 227
- Inscription: Sam 12 Fév 2011 20:54
Re: [MAJ 2] Recherches et Avancées du Hack de la PS3...
- Code: Tout sélectionner
/*
2 * PS3 address space management.
3 *
4 * Copyright (C) 2006 Sony Computer Entertainment Inc.
5 * Copyright 2006 Sony Corp.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include <linux/kernel.h>
22 #include <linux/module.h>
23 #include <linux/memory_hotplug.h>
24
25 #include <asm/firmware.h>
26 #include <asm/lmb.h>
27 #include <asm/udbg.h>
28 #include <asm/lv1call.h>
29
30 #include "platform.h"
31
32 #if defined(DEBUG)
33 #define DBG udbg_printf
34 #else
35 #define DBG pr_debug
36 #endif
37
38 enum {
39 #if defined(CONFIG_PS3_USE_LPAR_ADDR)
40 USE_LPAR_ADDR = 1,
41 #else
42 USE_LPAR_ADDR = 0,
43 #endif
44 #if defined(CONFIG_PS3_DYNAMIC_DMA)
45 USE_DYNAMIC_DMA = 1,
46 #else
47 USE_DYNAMIC_DMA = 0,
48 #endif
49 };
50
51 enum {
52 PAGE_SHIFT_4K = 12U,
53 PAGE_SHIFT_64K = 16U,
54 PAGE_SHIFT_16M = 24U,
55 };
56
57 static unsigned long make_page_sizes(unsigned long a, unsigned long b)
58 {
59 return (a << 56) | (b << 48);
60 }
61
62 enum {
63 ALLOCATE_MEMORY_TRY_ALT_UNIT = 0X04,
64 ALLOCATE_MEMORY_ADDR_ZERO = 0X08,
65 };
66
67 /* valid htab sizes are {18,19,20} = 256K, 512K, 1M */
68
69 enum {
70 HTAB_SIZE_MAX = 20U, /* HV limit of 1MB */
71 HTAB_SIZE_MIN = 18U, /* CPU limit of 256KB */
72 };
73
74 /*============================================================================*/
75 /* virtual address space routines */
76 /*============================================================================*/
77
78 /**
79 * struct mem_region - memory region structure
80 * @base: base address
81 * @size: size in bytes
82 * @offset: difference between base and rm.size
83 */
84
85 struct mem_region {
86 unsigned long base;
87 unsigned long size;
88 unsigned long offset;
89 };
90
91 /**
92 * struct map - address space state variables holder
93 * @total: total memory available as reported by HV
94 * @vas_id - HV virtual address space id
95 * @htab_size: htab size in bytes
96 *
97 * The HV virtual address space (vas) allows for hotplug memory regions.
98 * Memory regions can be created and destroyed in the vas at runtime.
99 * @rm: real mode (bootmem) region
100 * @r1: hotplug memory region(s)
101 *
102 * ps3 addresses
103 * virt_addr: a cpu 'translated' effective address
104 * phys_addr: an address in what Linux thinks is the physical address space
105 * lpar_addr: an address in the HV virtual address space
106 * bus_addr: an io controller 'translated' address on a device bus
107 */
108
109 struct map {
110 unsigned long total;
111 unsigned long vas_id;
112 unsigned long htab_size;
113 struct mem_region rm;
114 struct mem_region r1;
115 };
116
117 #define debug_dump_map(x) _debug_dump_map(x, __func__, __LINE__)
118 static void __maybe_unused _debug_dump_map(const struct map *m,
119 const char *func, int line)
120 {
121 DBG("%s:%d: map.total = %lxh\n", func, line, m->total);
122 DBG("%s:%d: map.rm.size = %lxh\n", func, line, m->rm.size);
123 DBG("%s:%d: map.vas_id = %lu\n", func, line, m->vas_id);
124 DBG("%s:%d: map.htab_size = %lxh\n", func, line, m->htab_size);
125 DBG("%s:%d: map.r1.base = %lxh\n", func, line, m->r1.base);
126 DBG("%s:%d: map.r1.offset = %lxh\n", func, line, m->r1.offset);
127 DBG("%s:%d: map.r1.size = %lxh\n", func, line, m->r1.size);
128 }
129
130 static struct map map;
131
132 /**
133 * ps3_mm_phys_to_lpar - translate a linux physical address to lpar address
134 * @phys_addr: linux physical address
135 */
136
137 unsigned long ps3_mm_phys_to_lpar(unsigned long phys_addr)
138 {
139 BUG_ON(is_kernel_addr(phys_addr));
140 if (USE_LPAR_ADDR)
141 return phys_addr;
142 else
143 return (phys_addr < map.rm.size || phys_addr >= map.total)
144 ? phys_addr : phys_addr + map.r1.offset;
145 }
146
147 EXPORT_SYMBOL(ps3_mm_phys_to_lpar);
148
149 /**
150 * ps3_mm_vas_create - create the virtual address space
151 */
152
153 void __init ps3_mm_vas_create(unsigned long* htab_size)
154 {
155 int result;
156 unsigned long start_address;
157 unsigned long size;
158 unsigned long access_right;
159 unsigned long max_page_size;
160 unsigned long flags;
161
162 result = lv1_query_logical_partition_address_region_info(0,
163 &start_address, &size, &access_right, &max_page_size,
164 &flags);
165
166 if (result) {
167 DBG("%s:%d: lv1_query_logical_partition_address_region_info "
168 "failed: %s\n", __func__, __LINE__,
169 ps3_result(result));
170 goto fail;
171 }
172
173 if (max_page_size < PAGE_SHIFT_16M) {
174 DBG("%s:%d: bad max_page_size %lxh\n", __func__, __LINE__,
175 max_page_size);
176 goto fail;
177 }
178
179 BUILD_BUG_ON(CONFIG_PS3_HTAB_SIZE > HTAB_SIZE_MAX);
180 BUILD_BUG_ON(CONFIG_PS3_HTAB_SIZE < HTAB_SIZE_MIN);
181
182 result = lv1_construct_virtual_address_space(CONFIG_PS3_HTAB_SIZE,
183 2, make_page_sizes(PAGE_SHIFT_16M, PAGE_SHIFT_64K),
184 &map.vas_id, &map.htab_size);
185
186 if (result) {
187 DBG("%s:%d: lv1_construct_virtual_address_space failed: %s\n",
188 __func__, __LINE__, ps3_result(result));
189 goto fail;
190 }
191
192 result = lv1_select_virtual_address_space(map.vas_id);
193
194 if (result) {
195 DBG("%s:%d: lv1_select_virtual_address_space failed: %s\n",
196 __func__, __LINE__, ps3_result(result));
197 goto fail;
198 }
199
200 *htab_size = map.htab_size;
201
202 debug_dump_map(&map);
203
204 return;
205
206 fail:
207 panic("ps3_mm_vas_create failed");
208 }
209
210 /**
211 * ps3_mm_vas_destroy -
212 */
213
214 void ps3_mm_vas_destroy(void)
215 {
216 int result;
217
218 DBG("%s:%d: map.vas_id = %lu\n", __func__, __LINE__, map.vas_id);
219
220 if (map.vas_id) {
221 result = lv1_select_virtual_address_space(0);
222 BUG_ON(result);
223 result = lv1_destruct_virtual_address_space(map.vas_id);
224 BUG_ON(result);
225 map.vas_id = 0;
226 }
227 }
228
229 /*============================================================================*/
230 /* memory hotplug routines */
231 /*============================================================================*/
232
233 /**
234 * ps3_mm_region_create - create a memory region in the vas
235 * @r: pointer to a struct mem_region to accept initialized values
236 * @size: requested region size
237 *
238 * This implementation creates the region with the vas large page size.
239 * @size is rounded down to a multiple of the vas large page size.
240 */
241
242 static int ps3_mm_region_create(struct mem_region *r, unsigned long size)
243 {
244 int result;
245 unsigned long muid;
246
247 r->size = _ALIGN_DOWN(size, 1 << PAGE_SHIFT_16M);
248
249 DBG("%s:%d requested %lxh\n", __func__, __LINE__, size);
250 DBG("%s:%d actual %lxh\n", __func__, __LINE__, r->size);
251 DBG("%s:%d difference %lxh (%luMB)\n", __func__, __LINE__,
252 (unsigned long)(size - r->size),
253 (size - r->size) / 1024 / 1024);
254
255 if (r->size == 0) {
256 DBG("%s:%d: size == 0\n", __func__, __LINE__);
257 result = -1;
258 goto zero_region;
259 }
260
261 result = lv1_allocate_memory(r->size, PAGE_SHIFT_16M, 0,
262 ALLOCATE_MEMORY_TRY_ALT_UNIT, &r->base, &muid);
263
264 if (result || r->base < map.rm.size) {
265 DBG("%s:%d: lv1_allocate_memory failed: %s\n",
266 __func__, __LINE__, ps3_result(result));
267 goto zero_region;
268 }
269
270 r->offset = r->base - map.rm.size;
271 return result;
272
273 zero_region:
274 r->size = r->base = r->offset = 0;
275 return result;
276 }
277
278 /**
279 * ps3_mm_region_destroy - destroy a memory region
280 * @r: pointer to struct mem_region
281 */
282
283 static void ps3_mm_region_destroy(struct mem_region *r)
284 {
285 int result;
286
287 DBG("%s:%d: r->base = %lxh\n", __func__, __LINE__, r->base);
288 if (r->base) {
289 result = lv1_release_memory(r->base);
290 BUG_ON(result);
291 r->size = r->base = r->offset = 0;
292 map.total = map.rm.size;
293 }
294 }
295
296 /**
297 * ps3_mm_add_memory - hot add memory
298 */
299
300 static int __init ps3_mm_add_memory(void)
301 {
302 int result;
303 unsigned long start_addr;
304 unsigned long start_pfn;
305 unsigned long nr_pages;
306
307 if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
308 return -ENODEV;
309
310 BUG_ON(!mem_init_done);
311
312 start_addr = USE_LPAR_ADDR ? map.r1.base : map.rm.size;
313 start_pfn = start_addr >> PAGE_SHIFT;
314 nr_pages = (map.r1.size + PAGE_SIZE - 1) >> PAGE_SHIFT;
315
316 DBG("%s:%d: start_addr %lxh, start_pfn %lxh, nr_pages %lxh\n",
317 __func__, __LINE__, start_addr, start_pfn, nr_pages);
318
319 result = add_memory(0, start_addr, map.r1.size);
320
321 if (result) {
322 DBG("%s:%d: add_memory failed: (%d)\n",
323 __func__, __LINE__, result);
324 return result;
325 }
326
327 result = online_pages(start_pfn, nr_pages);
328
329 if (result)
330 DBG("%s:%d: online_pages failed: (%d)\n",
331 __func__, __LINE__, result);
332
333 return result;
334 }
335
336 core_initcall(ps3_mm_add_memory);
337
338 /*============================================================================*/
339 /* dma routines */
340 /*============================================================================*/
341
342 /**
343 * dma_sb_lpar_to_bus - Translate an lpar address to ioc mapped bus address.
344 * @r: pointer to dma region structure
345 * @lpar_addr: HV lpar address
346 */
347
348 static unsigned long dma_sb_lpar_to_bus(struct ps3_dma_region *r,
349 unsigned long lpar_addr)
350 {
351 if (lpar_addr >= map.rm.size)
352 lpar_addr -= map.r1.offset;
353 BUG_ON(lpar_addr < r->offset);
354 BUG_ON(lpar_addr >= r->offset + r->len);
355 return r->bus_addr + lpar_addr - r->offset;
356 }
357
358 #define dma_dump_region(_a) _dma_dump_region(_a, __func__, __LINE__)
359 static void __maybe_unused _dma_dump_region(const struct ps3_dma_region *r,
360 const char *func, int line)
361 {
362 DBG("%s:%d: dev %u:%u\n", func, line, r->dev->bus_id,
363 r->dev->dev_id);
364 DBG("%s:%d: page_size %u\n", func, line, r->page_size);
365 DBG("%s:%d: bus_addr %lxh\n", func, line, r->bus_addr);
366 DBG("%s:%d: len %lxh\n", func, line, r->len);
367 DBG("%s:%d: offset %lxh\n", func, line, r->offset);
368 }
369
370 /**
371 * dma_chunk - A chunk of dma pages mapped by the io controller.
372 * @region - The dma region that owns this chunk.
373 * @lpar_addr: Starting lpar address of the area to map.
374 * @bus_addr: Starting ioc bus address of the area to map.
375 * @len: Length in bytes of the area to map.
376 * @link: A struct list_head used with struct ps3_dma_region.chunk_list, the
377 * list of all chuncks owned by the region.
378 *
379 * This implementation uses a very simple dma page manager
380 * based on the dma_chunk structure. This scheme assumes
381 * that all drivers use very well behaved dma ops.
382 */
383
384 struct dma_chunk {
385 struct ps3_dma_region *region;
386 unsigned long lpar_addr;
387 unsigned long bus_addr;
388 unsigned long len;
389 struct list_head link;
390 unsigned int usage_count;
391 };
392
393 #define dma_dump_chunk(_a) _dma_dump_chunk(_a, __func__, __LINE__)
394 static void _dma_dump_chunk (const struct dma_chunk* c, const char* func,
395 int line)
396 {
397 DBG("%s:%d: r.dev %u:%u\n", func, line,
398 c->region->dev->bus_id, c->region->dev->dev_id);
399 DBG("%s:%d: r.bus_addr %lxh\n", func, line, c->region->bus_addr);
400 DBG("%s:%d: r.page_size %u\n", func, line, c->region->page_size);
401 DBG("%s:%d: r.len %lxh\n", func, line, c->region->len);
402 DBG("%s:%d: r.offset %lxh\n", func, line, c->region->offset);
403 DBG("%s:%d: c.lpar_addr %lxh\n", func, line, c->lpar_addr);
404 DBG("%s:%d: c.bus_addr %lxh\n", func, line, c->bus_addr);
405 DBG("%s:%d: c.len %lxh\n", func, line, c->len);
406 }
407
408 static struct dma_chunk * dma_find_chunk(struct ps3_dma_region *r,
409 unsigned long bus_addr, unsigned long len)
410 {
411 struct dma_chunk *c;
412 unsigned long aligned_bus = _ALIGN_DOWN(bus_addr, 1 << r->page_size);
413 unsigned long aligned_len = _ALIGN_UP(len+bus_addr-aligned_bus,
414 1 << r->page_size);
415
416 list_for_each_entry(c, &r->chunk_list.head, link) {
417 /* intersection */
418 if (aligned_bus >= c->bus_addr &&
419 aligned_bus + aligned_len <= c->bus_addr + c->len)
420 return c;
421
422 /* below */
423 if (aligned_bus + aligned_len <= c->bus_addr)
424 continue;
425
426 /* above */
427 if (aligned_bus >= c->bus_addr + c->len)
428 continue;
429
430 /* we don't handle the multi-chunk case for now */
431 dma_dump_chunk(c);
432 BUG();
433 }
434 return NULL;
435 }
436
437 static struct dma_chunk *dma_find_chunk_lpar(struct ps3_dma_region *r,
438 unsigned long lpar_addr, unsigned long len)
439 {
440 struct dma_chunk *c;
441 unsigned long aligned_lpar = _ALIGN_DOWN(lpar_addr, 1 << r->page_size);
442 unsigned long aligned_len = _ALIGN_UP(len + lpar_addr - aligned_lpar,
443 1 << r->page_size);
444
445 list_for_each_entry(c, &r->chunk_list.head, link) {
446 /* intersection */
447 if (c->lpar_addr <= aligned_lpar &&
448 aligned_lpar < c->lpar_addr + c->len) {
449 if (aligned_lpar + aligned_len <= c->lpar_addr + c->len)
450 return c;
451 else {
452 dma_dump_chunk(c);
453 BUG();
454 }
455 }
456 /* below */
457 if (aligned_lpar + aligned_len <= c->lpar_addr) {
458 continue;
459 }
460 /* above */
461 if (c->lpar_addr + c->len <= aligned_lpar) {
462 continue;
463 }
464 }
465 return NULL;
466 }
467
468 static int dma_sb_free_chunk(struct dma_chunk *c)
469 {
470 int result = 0;
471
472 if (c->bus_addr) {
473 result = lv1_unmap_device_dma_region(c->region->dev->bus_id,
474 c->region->dev->dev_id, c->bus_addr, c->len);
475 BUG_ON(result);
476 }
477
478 kfree(c);
479 return result;
480 }
481
482 static int dma_ioc0_free_chunk(struct dma_chunk *c)
483 {
484 int result = 0;
485 int iopage;
486 unsigned long offset;
487 struct ps3_dma_region *r = c->region;
488
489 DBG("%s:start\n", __func__);
490 for (iopage = 0; iopage < (c->len >> r->page_size); iopage++) {
491 offset = (1 << r->page_size) * iopage;
492 /* put INVALID entry */
493 result = lv1_put_iopte(0,
494 c->bus_addr + offset,
495 c->lpar_addr + offset,
496 r->ioid,
497 0);
498 DBG("%s: bus=%#lx, lpar=%#lx, ioid=%d\n", __func__,
499 c->bus_addr + offset,
500 c->lpar_addr + offset,
501 r->ioid);
502
503 if (result) {
504 DBG("%s:%d: lv1_put_iopte failed: %s\n", __func__,
505 __LINE__, ps3_result(result));
506 }
507 }
508 kfree(c);
509 DBG("%s:end\n", __func__);
510 return result;
511 }
512
513 /**
514 * dma_sb_map_pages - Maps dma pages into the io controller bus address space.
515 * @r: Pointer to a struct ps3_dma_region.
516 * @phys_addr: Starting physical address of the area to map.
517 * @len: Length in bytes of the area to map.
518 * c_out: A pointer to receive an allocated struct dma_chunk for this area.
519 *
520 * This is the lowest level dma mapping routine, and is the one that will
521 * make the HV call to add the pages into the io controller address space.
522 */
523
524 static int dma_sb_map_pages(struct ps3_dma_region *r, unsigned long phys_addr,
525 unsigned long len, struct dma_chunk **c_out, u64 iopte_flag)
526 {
527 int result;
528 struct dma_chunk *c;
529
530 c = kzalloc(sizeof(struct dma_chunk), GFP_ATOMIC);
531
532 if (!c) {
533 result = -ENOMEM;
534 goto fail_alloc;
535 }
536
537 c->region = r;
538 c->lpar_addr = ps3_mm_phys_to_lpar(phys_addr);
539 c->bus_addr = dma_sb_lpar_to_bus(r, c->lpar_addr);
540 c->len = len;
541
542 BUG_ON(iopte_flag != 0xf800000000000000UL);
543 result = lv1_map_device_dma_region(c->region->dev->bus_id,
544 c->region->dev->dev_id, c->lpar_addr,
545 c->bus_addr, c->len, iopte_flag);
546 if (result) {
547 DBG("%s:%d: lv1_map_device_dma_region failed: %s\n",
548 __func__, __LINE__, ps3_result(result));
549 goto fail_map;
550 }
551
552 list_add(&c->link, &r->chunk_list.head);
553
554 *c_out = c;
555 return 0;
556
557 fail_map:
558 kfree(c);
559 fail_alloc:
560 *c_out = NULL;
561 DBG(" <- %s:%d\n", __func__, __LINE__);
562 return result;
563 }
564
565 static int dma_ioc0_map_pages(struct ps3_dma_region *r, unsigned long phys_addr,
566 unsigned long len, struct dma_chunk **c_out,
567 u64 iopte_flag)
568 {
569 int result;
570 struct dma_chunk *c, *last;
571 int iopage, pages;
572 unsigned long offset;
573
574 DBG(KERN_ERR "%s: phy=%#lx, lpar%#lx, len=%#lx\n", __func__,
575 phys_addr, ps3_mm_phys_to_lpar(phys_addr), len);
576 c = kzalloc(sizeof(struct dma_chunk), GFP_ATOMIC);
577
578 if (!c) {
579 result = -ENOMEM;
580 goto fail_alloc;
581 }
582
583 c->region = r;
584 c->len = len;
585 c->lpar_addr = ps3_mm_phys_to_lpar(phys_addr);
586 /* allocate IO address */
587 if (list_empty(&r->chunk_list.head)) {
588 /* first one */
589 c->bus_addr = r->bus_addr;
590 } else {
591 /* derive from last bus addr*/
592 last = list_entry(r->chunk_list.head.next,
593 struct dma_chunk, link);
594 c->bus_addr = last->bus_addr + last->len;
595 DBG("%s: last bus=%#lx, len=%#lx\n", __func__,
596 last->bus_addr, last->len);
597 }
598
599 /* FIXME: check whether length exceeds region size */
600
601 /* build ioptes for the area */
602 pages = len >> r->page_size;
603 DBG("%s: pgsize=%#x len=%#lx pages=%#x iopteflag=%#lx\n", __func__,
604 r->page_size, r->len, pages, iopte_flag);
605 for (iopage = 0; iopage < pages; iopage++) {
606 offset = (1 << r->page_size) * iopage;
607 result = lv1_put_iopte(0,
608 c->bus_addr + offset,
609 c->lpar_addr + offset,
610 r->ioid,
611 iopte_flag);
612 if (result) {
613 printk(KERN_WARNING "%s:%d: lv1_map_device_dma_region "
614 "failed: %s\n", __func__, __LINE__,
615 ps3_result(result));
616 goto fail_map;
617 }
618 DBG("%s: pg=%d bus=%#lx, lpar=%#lx, ioid=%#x\n", __func__,
619 iopage, c->bus_addr + offset, c->lpar_addr + offset,
620 r->ioid);
621 }
622
623 /* be sure that last allocated one is inserted at head */
624 list_add(&c->link, &r->chunk_list.head);
625
626 *c_out = c;
627 DBG("%s: end\n", __func__);
628 return 0;
629
630 fail_map:
631 for (iopage--; 0 <= iopage; iopage--) {
632 lv1_put_iopte(0,
633 c->bus_addr + offset,
634 c->lpar_addr + offset,
635 r->ioid,
636 0);
637 }
638 kfree(c);
639 fail_alloc:
640 *c_out = NULL;
641 return result;
642 }
643
644 /**
645 * dma_sb_region_create - Create a device dma region.
646 * @r: Pointer to a struct ps3_dma_region.
647 *
648 * This is the lowest level dma region create routine, and is the one that
649 * will make the HV call to create the region.
650 */
651
652 static int dma_sb_region_create(struct ps3_dma_region *r)
653 {
654 int result;
655
656 pr_info(" -> %s:%d:\n", __func__, __LINE__);
657
658 BUG_ON(!r);
659
660 if (!r->dev->bus_id) {
661 pr_info("%s:%d: %u:%u no dma\n", __func__, __LINE__,
662 r->dev->bus_id, r->dev->dev_id);
663 return 0;
664 }
665
666 DBG("%s:%u: len = 0x%lx, page_size = %u, offset = 0x%lx\n", __func__,
667 __LINE__, r->len, r->page_size, r->offset);
668
669 BUG_ON(!r->len);
670 BUG_ON(!r->page_size);
671 BUG_ON(!r->region_ops);
672
673 INIT_LIST_HEAD(&r->chunk_list.head);
674 spin_lock_init(&r->chunk_list.lock);
675
676 result = lv1_allocate_device_dma_region(r->dev->bus_id, r->dev->dev_id,
677 roundup_pow_of_two(r->len), r->page_size, r->region_type,
678 &r->bus_addr);
679
680 if (result) {
681 DBG("%s:%d: lv1_allocate_device_dma_region failed: %s\n",
682 __func__, __LINE__, ps3_result(result));
683 r->len = r->bus_addr = 0;
684 }
685
686 return result;
687 }
688
689 static int dma_ioc0_region_create(struct ps3_dma_region *r)
690 {
691 int result;
692
693 INIT_LIST_HEAD(&r->chunk_list.head);
694 spin_lock_init(&r->chunk_list.lock);
695
696 result = lv1_allocate_io_segment(0,
697 r->len,
698 r->page_size,
699 &r->bus_addr);
700 if (result) {
701 DBG("%s:%d: lv1_allocate_io_segment failed: %s\n",
702 __func__, __LINE__, ps3_result(result));
703 r->len = r->bus_addr = 0;
704 }
705 DBG("%s: len=%#lx, pg=%d, bus=%#lx\n", __func__,
706 r->len, r->page_size, r->bus_addr);
707 return result;
708 }
709
710 /**
711 * dma_region_free - Free a device dma region.
712 * @r: Pointer to a struct ps3_dma_region.
713 *
714 * This is the lowest level dma region free routine, and is the one that
715 * will make the HV call to free the region.
716 */
717
718 static int dma_sb_region_free(struct ps3_dma_region *r)
719 {
720 int result;
721 struct dma_chunk *c;
722 struct dma_chunk *tmp;
723
724 BUG_ON(!r);
725
726 if (!r->dev->bus_id) {
727 pr_info("%s:%d: %u:%u no dma\n", __func__, __LINE__,
728 r->dev->bus_id, r->dev->dev_id);
729 return 0;
730 }
731
732 list_for_each_entry_safe(c, tmp, &r->chunk_list.head, link) {
733 list_del(&c->link);
734 dma_sb_free_chunk(c);
735 }
736
737 result = lv1_free_device_dma_region(r->dev->bus_id, r->dev->dev_id,
738 r->bus_addr);
739
740 if (result)
741 DBG("%s:%d: lv1_free_device_dma_region failed: %s\n",
742 __func__, __LINE__, ps3_result(result));
743
744 r->bus_addr = 0;
745
746 return result;
747 }
748
749 static int dma_ioc0_region_free(struct ps3_dma_region *r)
750 {
751 int result;
752 struct dma_chunk *c, *n;
753
754 DBG("%s: start\n", __func__);
755 list_for_each_entry_safe(c, n, &r->chunk_list.head, link) {
756 list_del(&c->link);
757 dma_ioc0_free_chunk(c);
758 }
759
760 result = lv1_release_io_segment(0, r->bus_addr);
761
762 if (result)
763 DBG("%s:%d: lv1_free_device_dma_region failed: %s\n",
764 __func__, __LINE__, ps3_result(result));
765
766 r->bus_addr = 0;
767 DBG("%s: end\n", __func__);
768
769 return result;
770 }
771
772 /**
773 * dma_sb_map_area - Map an area of memory into a device dma region.
774 * @r: Pointer to a struct ps3_dma_region.
775 * @virt_addr: Starting virtual address of the area to map.
776 * @len: Length in bytes of the area to map.
777 * @bus_addr: A pointer to return the starting ioc bus address of the area to
778 * map.
779 *
780 * This is the common dma mapping routine.
781 */
782
783 static int dma_sb_map_area(struct ps3_dma_region *r, unsigned long virt_addr,
784 unsigned long len, unsigned long *bus_addr,
785 u64 iopte_flag)
786 {
787 int result;
788 unsigned long flags;
789 struct dma_chunk *c;
790 unsigned long phys_addr = is_kernel_addr(virt_addr) ? __pa(virt_addr)
791 : virt_addr;
792 unsigned long aligned_phys = _ALIGN_DOWN(phys_addr, 1 << r->page_size);
793 unsigned long aligned_len = _ALIGN_UP(len + phys_addr - aligned_phys,
794 1 << r->page_size);
795 *bus_addr = dma_sb_lpar_to_bus(r, ps3_mm_phys_to_lpar(phys_addr));
796
797 if (!USE_DYNAMIC_DMA) {
798 unsigned long lpar_addr = ps3_mm_phys_to_lpar(phys_addr);
799 DBG(" -> %s:%d\n", __func__, __LINE__);
800 DBG("%s:%d virt_addr %lxh\n", __func__, __LINE__,
801 virt_addr);
802 DBG("%s:%d phys_addr %lxh\n", __func__, __LINE__,
803 phys_addr);
804 DBG("%s:%d lpar_addr %lxh\n", __func__, __LINE__,
805 lpar_addr);
806 DBG("%s:%d len %lxh\n", __func__, __LINE__, len);
807 DBG("%s:%d bus_addr %lxh (%lxh)\n", __func__, __LINE__,
808 *bus_addr, len);
809 }
810
811 spin_lock_irqsave(&r->chunk_list.lock, flags);
812 c = dma_find_chunk(r, *bus_addr, len);
813
814 if (c) {
815 DBG("%s:%d: reusing mapped chunk", __func__, __LINE__);
816 dma_dump_chunk(c);
817 c->usage_count++;
818 spin_unlock_irqrestore(&r->chunk_list.lock, flags);
819 return 0;
820 }
821
822 result = dma_sb_map_pages(r, aligned_phys, aligned_len, &c, iopte_flag);
823
824 if (result) {
825 *bus_addr = 0;
826 DBG("%s:%d: dma_sb_map_pages failed (%d)\n",
827 __func__, __LINE__, result);
828 spin_unlock_irqrestore(&r->chunk_list.lock, flags);
829 return result;
830 }
831
832 c->usage_count = 1;
833
834 spin_unlock_irqrestore(&r->chunk_list.lock, flags);
835 return result;
836 }
837
838 static int dma_ioc0_map_area(struct ps3_dma_region *r, unsigned long virt_addr,
839 unsigned long len, unsigned long *bus_addr,
840 u64 iopte_flag)
841 {
842 int result;
843 unsigned long flags;
844 struct dma_chunk *c;
845 unsigned long phys_addr = is_kernel_addr(virt_addr) ? __pa(virt_addr)
846 : virt_addr;
847 unsigned long aligned_phys = _ALIGN_DOWN(phys_addr, 1 << r->page_size);
848 unsigned long aligned_len = _ALIGN_UP(len + phys_addr - aligned_phys,
849 1 << r->page_size);
850
851 DBG(KERN_ERR "%s: vaddr=%#lx, len=%#lx\n", __func__,
852 virt_addr, len);
853 DBG(KERN_ERR "%s: ph=%#lx a_ph=%#lx a_l=%#lx\n", __func__,
854 phys_addr, aligned_phys, aligned_len);
855
856 spin_lock_irqsave(&r->chunk_list.lock, flags);
857 c = dma_find_chunk_lpar(r, ps3_mm_phys_to_lpar(phys_addr), len);
858
859 if (c) {
860 /* FIXME */
861 BUG();
862 *bus_addr = c->bus_addr + phys_addr - aligned_phys;
863 c->usage_count++;
864 spin_unlock_irqrestore(&r->chunk_list.lock, flags);
865 return 0;
866 }
867
868 result = dma_ioc0_map_pages(r, aligned_phys, aligned_len, &c,
869 iopte_flag);
870
871 if (result) {
872 *bus_addr = 0;
873 DBG("%s:%d: dma_ioc0_map_pages failed (%d)\n",
874 __func__, __LINE__, result);
875 spin_unlock_irqrestore(&r->chunk_list.lock, flags);
876 return result;
877 }
878 *bus_addr = c->bus_addr + phys_addr - aligned_phys;
879 DBG("%s: va=%#lx pa=%#lx a_pa=%#lx bus=%#lx\n", __func__,
880 virt_addr, phys_addr, aligned_phys, *bus_addr);
881 c->usage_count = 1;
882
883 spin_unlock_irqrestore(&r->chunk_list.lock, flags);
884 return result;
885 }
886
887 /**
888 * dma_sb_unmap_area - Unmap an area of memory from a device dma region.
889 * @r: Pointer to a struct ps3_dma_region.
890 * @bus_addr: The starting ioc bus address of the area to unmap.
891 * @len: Length in bytes of the area to unmap.
892 *
893 * This is the common dma unmap routine.
894 */
895
896 static int dma_sb_unmap_area(struct ps3_dma_region *r, unsigned long bus_addr,
897 unsigned long len)
898 {
899 unsigned long flags;
900 struct dma_chunk *c;
901
902 spin_lock_irqsave(&r->chunk_list.lock, flags);
903 c = dma_find_chunk(r, bus_addr, len);
904
905 if (!c) {
906 unsigned long aligned_bus = _ALIGN_DOWN(bus_addr,
907 1 << r->page_size);
908 unsigned long aligned_len = _ALIGN_UP(len + bus_addr
909 - aligned_bus, 1 << r->page_size);
910 DBG("%s:%d: not found: bus_addr %lxh\n",
911 __func__, __LINE__, bus_addr);
912 DBG("%s:%d: not found: len %lxh\n",
913 __func__, __LINE__, len);
914 DBG("%s:%d: not found: aligned_bus %lxh\n",
915 __func__, __LINE__, aligned_bus);
916 DBG("%s:%d: not found: aligned_len %lxh\n",
917 __func__, __LINE__, aligned_len);
918 BUG();
919 }
920
921 c->usage_count--;
922
923 if (!c->usage_count) {
924 list_del(&c->link);
925 dma_sb_free_chunk(c);
926 }
927
928 spin_unlock_irqrestore(&r->chunk_list.lock, flags);
929 return 0;
930 }
931
932 static int dma_ioc0_unmap_area(struct ps3_dma_region *r,
933 unsigned long bus_addr, unsigned long len)
934 {
935 unsigned long flags;
936 struct dma_chunk *c;
937
938 DBG("%s: start a=%#lx l=%#lx\n", __func__, bus_addr, len);
939 spin_lock_irqsave(&r->chunk_list.lock, flags);
940 c = dma_find_chunk(r, bus_addr, len);
941
942 if (!c) {
943 unsigned long aligned_bus = _ALIGN_DOWN(bus_addr,
944 1 << r->page_size);
945 unsigned long aligned_len = _ALIGN_UP(len + bus_addr
946 - aligned_bus,
947 1 << r->page_size);
948 DBG("%s:%d: not found: bus_addr %lxh\n",
949 __func__, __LINE__, bus_addr);
950 DBG("%s:%d: not found: len %lxh\n",
951 __func__, __LINE__, len);
952 DBG("%s:%d: not found: aligned_bus %lxh\n",
953 __func__, __LINE__, aligned_bus);
954 DBG("%s:%d: not found: aligned_len %lxh\n",
955 __func__, __LINE__, aligned_len);
956 BUG();
957 }
958
959 c->usage_count--;
960
961 if (!c->usage_count) {
962 list_del(&c->link);
963 dma_ioc0_free_chunk(c);
964 }
965
966 spin_unlock_irqrestore(&r->chunk_list.lock, flags);
967 DBG("%s: end\n", __func__);
968 return 0;
969 }
970
971 /**
972 * dma_sb_region_create_linear - Setup a linear dma mapping for a device.
973 * @r: Pointer to a struct ps3_dma_region.
974 *
975 * This routine creates an HV dma region for the device and maps all available
976 * ram into the io controller bus address space.
977 */
978
979 static int dma_sb_region_create_linear(struct ps3_dma_region *r)
980 {
981 int result;
982 unsigned long virt_addr, len, tmp;
983
984 if (r->len > 16*1024*1024) { /* FIXME: need proper fix */
985 /* force 16M dma pages for linear mapping */
986 if (r->page_size != PS3_DMA_16M) {
987 pr_info("%s:%d: forcing 16M pages for linear map\n",
988 __func__, __LINE__);
989 r->page_size = PS3_DMA_16M;
990 r->len = _ALIGN_UP(r->len, 1 << r->page_size);
991 }
992 }
993
994 result = dma_sb_region_create(r);
995 BUG_ON(result);
996
997 if (r->offset < map.rm.size) {
998 /* Map (part of) 1st RAM chunk */
999 virt_addr = map.rm.base + r->offset;
1000 len = map.rm.size - r->offset;
1001 if (len > r->len)
1002 len = r->len;
1003 result = dma_sb_map_area(r, virt_addr, len, &tmp,
1004 IOPTE_PP_W | IOPTE_PP_R | IOPTE_SO_RW | IOPTE_M);
1005 BUG_ON(result);
1006 }
1007
1008 if (r->offset + r->len > map.rm.size) {
1009 /* Map (part of) 2nd RAM chunk */
1010 virt_addr = USE_LPAR_ADDR ? map.r1.base : map.rm.size;
1011 len = r->len;
1012 if (r->offset >= map.rm.size)
1013 virt_addr += r->offset - map.rm.size;
1014 else
1015 len -= map.rm.size - r->offset;
1016 result = dma_sb_map_area(r, virt_addr, len, &tmp,
1017 IOPTE_PP_W | IOPTE_PP_R | IOPTE_SO_RW | IOPTE_M);
1018 BUG_ON(result);
1019 }
1020
1021 return result;
1022 }
1023
1024 /**
1025 * dma_sb_region_free_linear - Free a linear dma mapping for a device.
1026 * @r: Pointer to a struct ps3_dma_region.
1027 *
1028 * This routine will unmap all mapped areas and free the HV dma region.
1029 */
1030
1031 static int dma_sb_region_free_linear(struct ps3_dma_region *r)
1032 {
1033 int result;
1034 unsigned long bus_addr, len, lpar_addr;
1035
1036 if (r->offset < map.rm.size) {
1037 /* Unmap (part of) 1st RAM chunk */
1038 lpar_addr = map.rm.base + r->offset;
1039 len = map.rm.size - r->offset;
1040 if (len > r->len)
1041 len = r->len;
1042 bus_addr = dma_sb_lpar_to_bus(r, lpar_addr);
1043 result = dma_sb_unmap_area(r, bus_addr, len);
1044 BUG_ON(result);
1045 }
1046
1047 if (r->offset + r->len > map.rm.size) {
1048 /* Unmap (part of) 2nd RAM chunk */
1049 lpar_addr = map.r1.base;
1050 len = r->len;
1051 if (r->offset >= map.rm.size)
1052 lpar_addr += r->offset - map.rm.size;
1053 else
1054 len -= map.rm.size - r->offset;
1055 bus_addr = dma_sb_lpar_to_bus(r, lpar_addr);
1056 result = dma_sb_unmap_area(r, bus_addr, len);
1057 BUG_ON(result);
1058 }
1059
1060 result = dma_sb_region_free(r);
1061 BUG_ON(result);
1062
1063 return result;
1064 }
1065
1066 /**
1067 * dma_sb_map_area_linear - Map an area of memory into a device dma region.
1068 * @r: Pointer to a struct ps3_dma_region.
1069 * @virt_addr: Starting virtual address of the area to map.
1070 * @len: Length in bytes of the area to map.
1071 * @bus_addr: A pointer to return the starting ioc bus address of the area to
1072 * map.
1073 *
1074 * This routine just returns the corresponding bus address. Actual mapping
1075 * occurs in dma_region_create_linear().
1076 */
1077
1078 static int dma_sb_map_area_linear(struct ps3_dma_region *r,
1079 unsigned long virt_addr, unsigned long len, unsigned long *bus_addr,
1080 u64 iopte_flag)
1081 {
1082 unsigned long phys_addr = is_kernel_addr(virt_addr) ? __pa(virt_addr)
1083 : virt_addr;
1084 *bus_addr = dma_sb_lpar_to_bus(r, ps3_mm_phys_to_lpar(phys_addr));
1085 return 0;
1086 }
1087
1088 /**
1089 * dma_unmap_area_linear - Unmap an area of memory from a device dma region.
1090 * @r: Pointer to a struct ps3_dma_region.
1091 * @bus_addr: The starting ioc bus address of the area to unmap.
1092 * @len: Length in bytes of the area to unmap.
1093 *
1094 * This routine does nothing. Unmapping occurs in dma_sb_region_free_linear().
1095 */
1096
1097 static int dma_sb_unmap_area_linear(struct ps3_dma_region *r,
1098 unsigned long bus_addr, unsigned long len)
1099 {
1100 return 0;
1101 };
1102
1103 static const struct ps3_dma_region_ops ps3_dma_sb_region_ops = {
1104 .create = dma_sb_region_create,
1105 .free = dma_sb_region_free,
1106 .map = dma_sb_map_area,
1107 .unmap = dma_sb_unmap_area
1108 };
1109
1110 static const struct ps3_dma_region_ops ps3_dma_sb_region_linear_ops = {
1111 .create = dma_sb_region_create_linear,
1112 .free = dma_sb_region_free_linear,
1113 .map = dma_sb_map_area_linear,
1114 .unmap = dma_sb_unmap_area_linear
1115 };
1116
1117 static const struct ps3_dma_region_ops ps3_dma_ioc0_region_ops = {
1118 .create = dma_ioc0_region_create,
1119 .free = dma_ioc0_region_free,
1120 .map = dma_ioc0_map_area,
1121 .unmap = dma_ioc0_unmap_area
1122 };
1123
1124 int ps3_dma_region_init(struct ps3_system_bus_device *dev,
1125 struct ps3_dma_region *r, enum ps3_dma_page_size page_size,
1126 enum ps3_dma_region_type region_type, void *addr, unsigned long len)
1127 {
1128 unsigned long lpar_addr;
1129
1130 lpar_addr = addr ? ps3_mm_phys_to_lpar(__pa(addr)) : 0;
1131
1132 r->dev = dev;
1133 r->page_size = page_size;
1134 r->region_type = region_type;
1135 r->offset = lpar_addr;
1136 if (r->offset >= map.rm.size)
1137 r->offset -= map.r1.offset;
1138 r->len = len ? len : _ALIGN_UP(map.total, 1 << r->page_size);
1139
1140 switch (dev->dev_type) {
1141 case PS3_DEVICE_TYPE_SB:
1142 r->region_ops = (USE_DYNAMIC_DMA)
1143 ? &ps3_dma_sb_region_ops
1144 : &ps3_dma_sb_region_linear_ops;
1145 break;
1146 case PS3_DEVICE_TYPE_IOC0:
1147 r->region_ops = &ps3_dma_ioc0_region_ops;
1148 break;
1149 default:
1150 BUG();
1151 return -EINVAL;
1152 }
1153 return 0;
1154 }
1155 EXPORT_SYMBOL(ps3_dma_region_init);
1156
1157 int ps3_dma_region_create(struct ps3_dma_region *r)
1158 {
1159 BUG_ON(!r);
1160 BUG_ON(!r->region_ops);
1161 BUG_ON(!r->region_ops->create);
1162 return r->region_ops->create(r);
1163 }
1164 EXPORT_SYMBOL(ps3_dma_region_create);
1165
1166 int ps3_dma_region_free(struct ps3_dma_region *r)
1167 {
1168 BUG_ON(!r);
1169 BUG_ON(!r->region_ops);
1170 BUG_ON(!r->region_ops->free);
1171 return r->region_ops->free(r);
1172 }
1173 EXPORT_SYMBOL(ps3_dma_region_free);
1174
1175 int ps3_dma_map(struct ps3_dma_region *r, unsigned long virt_addr,
1176 unsigned long len, unsigned long *bus_addr,
1177 u64 iopte_flag)
1178 {
1179 return r->region_ops->map(r, virt_addr, len, bus_addr, iopte_flag);
1180 }
1181
1182 int ps3_dma_unmap(struct ps3_dma_region *r, unsigned long bus_addr,
1183 unsigned long len)
1184 {
1185 return r->region_ops->unmap(r, bus_addr, len);
1186 }
1187
1188 /*============================================================================*/
1189 /* system startup routines */
1190 /*============================================================================*/
1191
1192 /**
1193 * ps3_mm_init - initialize the address space state variables
1194 */
1195
1196 void __init ps3_mm_init(void)
1197 {
1198 int result;
1199
1200 DBG(" -> %s:%d\n", __func__, __LINE__);
1201
1202 result = ps3_repository_read_mm_info(&map.rm.base, &map.rm.size,
1203 &map.total);
1204
1205 if (result)
1206 panic("ps3_repository_read_mm_info() failed");
1207
1208 map.rm.offset = map.rm.base;
1209 map.vas_id = map.htab_size = 0;
1210
1211 /* this implementation assumes map.rm.base is zero */
1212
1213 BUG_ON(map.rm.base);
1214 BUG_ON(!map.rm.size);
1215
1216
1217 /* arrange to do this in ps3_mm_add_memory */
1218 ps3_mm_region_create(&map.r1, map.total - map.rm.size);
1219
1220 /* correct map.total for the real total amount of memory we use */
1221 map.total = map.rm.size + map.r1.size;
1222
1223 DBG(" <- %s:%d\n", __func__, __LINE__);
1224 }
1225
1226 /**
1227 * ps3_mm_shutdown - final cleanup of address space
1228 */
1229
1230 void ps3_mm_shutdown(void)
1231 {
1232 ps3_mm_region_destroy(&map.r1);
1233 }
- arisse2001
- Habitué
- Messages: 227
- Inscription: Sam 12 Fév 2011 20:54
Re: [MAJ 2] Recherches et Avancées du Hack de la PS3...
mapping ppc msg
- Code: Tout sélectionner
/*
* PS3 SMP routines.
*
* Copyright (C) 2006 Sony Computer Entertainment Inc.
* Copyright 2006 Sony Corp.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/kernel.h>
#include <linux/smp.h>
#include <asm/machdep.h>
#include <asm/udbg.h>
#include "platform.h"
#if defined(DEBUG)
#define DBG udbg_printf
#else
#define DBG pr_debug
#endif
static irqreturn_t ipi_function_handler(int irq, void *msg)
{
smp_message_recv((int)(long)msg);
return IRQ_HANDLED;
}
/**
* ps3_ipi_virqs - a per cpu array of virqs for ipi use
*/
#define MSG_COUNT 4
static DEFINE_PER_CPU(unsigned int, ps3_ipi_virqs[MSG_COUNT]);
static const char *names[MSG_COUNT] = {
"ipi call",
"ipi reschedule",
"ipi migrate",
"ipi debug brk"
};
static void do_message_pass(int target, int msg)
{
int result;
unsigned int virq;
if (msg >= MSG_COUNT) {
DBG("%s:%d: bad msg: %d\n", __func__, __LINE__, msg);
return;
}
virq = per_cpu(ps3_ipi_virqs, target)[msg];
result = ps3_send_event_locally(virq);
if (result)
DBG("%s:%d: ps3_send_event_locally(%d, %d) failed"
" (%d)\n", __func__, __LINE__, target, msg, result);
}
static void ps3_smp_message_pass(int target, int msg)
{
int cpu;
if (target < NR_CPUS)
do_message_pass(target, msg);
else if (target == MSG_ALL_BUT_SELF) {
for_each_online_cpu(cpu)
if (cpu != smp_processor_id())
do_message_pass(cpu, msg);
} else {
for_each_online_cpu(cpu)
do_message_pass(cpu, msg);
}
}
static int ps3_smp_probe(void)
{
return 2;
}
static void __init ps3_smp_setup_cpu(int cpu)
{
int result;
unsigned int *virqs = per_cpu(ps3_ipi_virqs, cpu);
int i;
DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu);
/*
* Check assumptions on ps3_ipi_virqs[] indexing. If this
* check fails, then a different mapping of PPC_MSG_
* to index needs to be setup.
*/
BUILD_BUG_ON(PPC_MSG_CALL_FUNCTION != 0);
BUILD_BUG_ON(PPC_MSG_RESCHEDULE != 1);
BUILD_BUG_ON(PPC_MSG_DEBUGGER_BREAK != 3);
for (i = 0; i < MSG_COUNT; i++) {
result = ps3_event_receive_port_setup(cpu, &virqs[i]);
if (result)
continue;
DBG("%s:%d: (%d, %d) => virq %u\n",
__func__, __LINE__, cpu, i, virqs[i]);
result = request_irq(virqs[i], ipi_function_handler,
IRQF_DISABLED, names[i], (void*)(long)i);
if (result)
virqs[i] = NO_IRQ;
}
ps3_register_ipi_debug_brk(cpu, virqs[PPC_MSG_DEBUGGER_BREAK]);
DBG(" <- %s:%d: (%d)\n", __func__, __LINE__, cpu);
}
void ps3_smp_cleanup_cpu(int cpu)
{
unsigned int *virqs = per_cpu(ps3_ipi_virqs, cpu);
int i;
DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu);
for (i = 0; i < MSG_COUNT; i++) {
/* Can't call free_irq from interrupt context. */
ps3_event_receive_port_destroy(virqs[i]);
virqs[i] = NO_IRQ;
}
DBG(" <- %s:%d: (%d)\n", __func__, __LINE__, cpu);
}
static struct smp_ops_t ps3_smp_ops = {
.probe = ps3_smp_probe,
.message_pass = ps3_smp_message_pass,
.kick_cpu = smp_generic_kick_cpu,
.setup_cpu = ps3_smp_setup_cpu,
};
void smp_init_ps3(void)
{
DBG(" -> %s\n", __func__);
smp_ops = &ps3_smp_ops;
DBG(" <- %s\n", __func__);
}
- arisse2001
- Habitué
- Messages: 227
- Inscription: Sam 12 Fév 2011 20:54
Re: [MAJ 2] Recherches et Avancées du Hack de la PS3...
jai une idée
tu update ta ps3 en 4.11 et puis tu downgrade ta ps3 en 3.55 mais sans le lv1-non-checks pour que le syscon soit a jour
puis tu crée un mdfw 3.55 :
dans le core os tu supprime tous les loader du 3.55 et tu remplace le lv0 du 3.55 par celui du 4.11 n'oublie pas de mettre le lv0.2
et tu installe . normalement ta ps3 doit crasher c pas grave tu dump la nor puis tu reflash avec l'original puis tu lance lunix sur ta ps3 et avec les outil du ps3 que jai poster tu flash ta ps3 avec la nor que tu viens de dumper maintenant on peux jouer avec le lv0 du 4.11
jai pas une e3-flasher pour tester
http://www.mediafire.com/?nruq8luyuaqh4vy
tu update ta ps3 en 4.11 et puis tu downgrade ta ps3 en 3.55 mais sans le lv1-non-checks pour que le syscon soit a jour
puis tu crée un mdfw 3.55 :
dans le core os tu supprime tous les loader du 3.55 et tu remplace le lv0 du 3.55 par celui du 4.11 n'oublie pas de mettre le lv0.2
et tu installe . normalement ta ps3 doit crasher c pas grave tu dump la nor puis tu reflash avec l'original puis tu lance lunix sur ta ps3 et avec les outil du ps3 que jai poster tu flash ta ps3 avec la nor que tu viens de dumper maintenant on peux jouer avec le lv0 du 4.11

jai pas une e3-flasher pour tester
http://www.mediafire.com/?nruq8luyuaqh4vy
- arisse2001
- Habitué
- Messages: 227
- Inscription: Sam 12 Fév 2011 20:54
Re: [MAJ 2] Recherches et Avancées du Hack de la PS3...
Penses tu que sa peut fonctionner sous CFW 3.56 ?
- raymanvtwo
- Expert
- Messages: 418
- Inscription: Dim 11 Sep 2011 16:31



