Welcome Anonymous !FaceBookGoogle +TwitterChaine YoutubeFlux Rss

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 ...

Panneau de modération ]

[MAJ 2] Recherches et Avancées du Hack de la PS3...

Venez apprendre a coder vos propres homebrew ou bien a partager votre savoir et partager ici aussi vos creations

Re: [MAJ 2] Recherches et Avancées du Hack de la PS3...

Messagepar arisse2001 » Dim 5 Fév 2012 22:41

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



Cliquez sur l'image pour agrandir



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


Cliquez sur l'image pour agrandir



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...

Messagepar Dr_Charlatan » Lun 6 Fév 2012 00:50

Arisse tu as le dump du LV0 et Metdlr du FW 4.00 original ?
PS-Addict , Le site francophone de référence sur le Hack de votre PS3.

Image
Avatar de l’utilisateur
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...

Messagepar arisse2001 » Lun 6 Fév 2012 01:35

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
arisse2001
Habitué
 
Messages: 227
Inscription: Sam 12 Fév 2011 20:54

Re: [MAJ 2] Recherches et Avancées du Hack de la PS3...

Messagepar raymanvtwo » Mer 22 Fév 2012 23:39

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 ^^
raymanvtwo
Expert
 
Messages: 418
Inscription: Dim 11 Sep 2011 16:31

Re: [MAJ 2] Recherches et Avancées du Hack de la PS3...

Messagepar kill3r » Sam 31 Mar 2012 11:00

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



Cliquez sur l'image pour agrandir



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


Cliquez sur l'image pour agrandir



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 ...
  • Si vous ne souhaitez pas que PS-Addict ferme, téléchargez quotidiennement ceci
  • Si vous me soutenez dans mes développements PS3, téléchargez quotidiennement ceci
  • Si vous me soutenez dans mes développements PSVita, téléchargez quotidiennement ceci

Important : lisez ceci
kill3r
Addict
 
Messages: 2249
Inscription: Lun 21 Sep 2009 13:41

Re: [MAJ 2] Recherches et Avancées du Hack de la PS3...

Messagepar arisse2001 » Sam 31 Mar 2012 13:09

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 :D :D
arisse2001
Habitué
 
Messages: 227
Inscription: Sam 12 Fév 2011 20:54

Re: [MAJ 2] Recherches et Avancées du Hack de la PS3...

Messagepar kill3r » Sam 31 Mar 2012 14:41

Pour le nom du fichier ça peut se comprendre ... mais croire que les loaders tiennent en quelques bytes ...
  • Si vous ne souhaitez pas que PS-Addict ferme, téléchargez quotidiennement ceci
  • Si vous me soutenez dans mes développements PS3, téléchargez quotidiennement ceci
  • Si vous me soutenez dans mes développements PSVita, téléchargez quotidiennement ceci

Important : lisez ceci
kill3r
Addict
 
Messages: 2249
Inscription: Lun 21 Sep 2009 13:41

Re: [MAJ 2] Recherches et Avancées du Hack de la PS3...

Messagepar arisse2001 » Dim 1 Avr 2012 01:00

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
arisse2001
Habitué
 
Messages: 227
Inscription: Sam 12 Fév 2011 20:54

Re: [MAJ 2] Recherches et Avancées du Hack de la PS3...

Messagepar arisse2001 » Dim 1 Avr 2012 01:25

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 :D
arisse2001
Habitué
 
Messages: 227
Inscription: Sam 12 Fév 2011 20:54

Re: [MAJ 2] Recherches et Avancées du Hack de la PS3...

Messagepar arisse2001 » Dim 1 Avr 2012 06:16

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...

Messagepar arisse2001 » Dim 1 Avr 2012 06:19

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...

Messagepar arisse2001 » Dim 1 Avr 2012 06:22

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...

Messagepar arisse2001 » Lun 2 Avr 2012 00:01

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...

Messagepar arisse2001 » Mer 4 Avr 2012 15:27

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 :D

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...

Messagepar raymanvtwo » Mer 4 Avr 2012 18:26

Penses tu que sa peut fonctionner sous CFW 3.56 ?
raymanvtwo
Expert
 
Messages: 418
Inscription: Dim 11 Sep 2011 16:31

PrécédenteSuivante

Réponse Rapide

 

Retourner vers Developpement Amateur et Customisation

Qui est en ligne

  • Au total il y a 3 utilisateurs en ligne :: 0 enregistré, 0 invisible et 3 invités (basées sur les utilisateurs actifs des 15 dernières minutes)
  • Le record du nombre d’utilisateurs en ligne est de 875, le Lun 17 Jan 2011 21:13
  • Utilisateurs parcourant ce forum: Aucun utilisateur enregistré et 3 invités