ppc.c 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278
  1. /*
  2. * QEMU generic PowerPC hardware System Emulator
  3. *
  4. * Copyright (c) 2003-2007 Jocelyn Mayer
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. * THE SOFTWARE.
  23. */
  24. #include "hw.h"
  25. #include "ppc.h"
  26. #include "qemu-timer.h"
  27. #include "sysemu.h"
  28. #include "nvram.h"
  29. #include "qemu-log.h"
  30. //#define PPC_DEBUG_IRQ
  31. //#define PPC_DEBUG_TB
  32. #ifdef PPC_DEBUG_IRQ
  33. # define LOG_IRQ(...) qemu_log_mask(CPU_LOG_INT, ## __VA_ARGS__)
  34. #else
  35. # define LOG_IRQ(...) do { } while (0)
  36. #endif
  37. #ifdef PPC_DEBUG_TB
  38. # define LOG_TB(...) qemu_log(__VA_ARGS__)
  39. #else
  40. # define LOG_TB(...) do { } while (0)
  41. #endif
  42. static void cpu_ppc_tb_stop (CPUState *env);
  43. static void cpu_ppc_tb_start (CPUState *env);
  44. static void ppc_set_irq (CPUState *env, int n_IRQ, int level)
  45. {
  46. if (level) {
  47. env->pending_interrupts |= 1 << n_IRQ;
  48. cpu_interrupt(env, CPU_INTERRUPT_HARD);
  49. } else {
  50. env->pending_interrupts &= ~(1 << n_IRQ);
  51. if (env->pending_interrupts == 0)
  52. cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
  53. }
  54. LOG_IRQ("%s: %p n_IRQ %d level %d => pending %08" PRIx32
  55. "req %08x\n", __func__, env, n_IRQ, level,
  56. env->pending_interrupts, env->interrupt_request);
  57. }
  58. /* PowerPC 6xx / 7xx internal IRQ controller */
  59. static void ppc6xx_set_irq (void *opaque, int pin, int level)
  60. {
  61. CPUState *env = opaque;
  62. int cur_level;
  63. LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
  64. env, pin, level);
  65. cur_level = (env->irq_input_state >> pin) & 1;
  66. /* Don't generate spurious events */
  67. if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
  68. switch (pin) {
  69. case PPC6xx_INPUT_TBEN:
  70. /* Level sensitive - active high */
  71. LOG_IRQ("%s: %s the time base\n",
  72. __func__, level ? "start" : "stop");
  73. if (level) {
  74. cpu_ppc_tb_start(env);
  75. } else {
  76. cpu_ppc_tb_stop(env);
  77. }
  78. case PPC6xx_INPUT_INT:
  79. /* Level sensitive - active high */
  80. LOG_IRQ("%s: set the external IRQ state to %d\n",
  81. __func__, level);
  82. ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
  83. break;
  84. case PPC6xx_INPUT_SMI:
  85. /* Level sensitive - active high */
  86. LOG_IRQ("%s: set the SMI IRQ state to %d\n",
  87. __func__, level);
  88. ppc_set_irq(env, PPC_INTERRUPT_SMI, level);
  89. break;
  90. case PPC6xx_INPUT_MCP:
  91. /* Negative edge sensitive */
  92. /* XXX: TODO: actual reaction may depends on HID0 status
  93. * 603/604/740/750: check HID0[EMCP]
  94. */
  95. if (cur_level == 1 && level == 0) {
  96. LOG_IRQ("%s: raise machine check state\n",
  97. __func__);
  98. ppc_set_irq(env, PPC_INTERRUPT_MCK, 1);
  99. }
  100. break;
  101. case PPC6xx_INPUT_CKSTP_IN:
  102. /* Level sensitive - active low */
  103. /* XXX: TODO: relay the signal to CKSTP_OUT pin */
  104. /* XXX: Note that the only way to restart the CPU is to reset it */
  105. if (level) {
  106. LOG_IRQ("%s: stop the CPU\n", __func__);
  107. env->halted = 1;
  108. }
  109. break;
  110. case PPC6xx_INPUT_HRESET:
  111. /* Level sensitive - active low */
  112. if (level) {
  113. LOG_IRQ("%s: reset the CPU\n", __func__);
  114. env->interrupt_request |= CPU_INTERRUPT_EXITTB;
  115. /* XXX: TOFIX */
  116. #if 0
  117. cpu_ppc_reset(env);
  118. #else
  119. qemu_system_reset_request();
  120. #endif
  121. }
  122. break;
  123. case PPC6xx_INPUT_SRESET:
  124. LOG_IRQ("%s: set the RESET IRQ state to %d\n",
  125. __func__, level);
  126. ppc_set_irq(env, PPC_INTERRUPT_RESET, level);
  127. break;
  128. default:
  129. /* Unknown pin - do nothing */
  130. LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
  131. return;
  132. }
  133. if (level)
  134. env->irq_input_state |= 1 << pin;
  135. else
  136. env->irq_input_state &= ~(1 << pin);
  137. }
  138. }
  139. void ppc6xx_irq_init (CPUState *env)
  140. {
  141. env->irq_inputs = (void **)qemu_allocate_irqs(&ppc6xx_set_irq, env,
  142. PPC6xx_INPUT_NB);
  143. }
  144. #if defined(TARGET_PPC64)
  145. /* PowerPC 970 internal IRQ controller */
  146. static void ppc970_set_irq (void *opaque, int pin, int level)
  147. {
  148. CPUState *env = opaque;
  149. int cur_level;
  150. LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
  151. env, pin, level);
  152. cur_level = (env->irq_input_state >> pin) & 1;
  153. /* Don't generate spurious events */
  154. if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
  155. switch (pin) {
  156. case PPC970_INPUT_INT:
  157. /* Level sensitive - active high */
  158. LOG_IRQ("%s: set the external IRQ state to %d\n",
  159. __func__, level);
  160. ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
  161. break;
  162. case PPC970_INPUT_THINT:
  163. /* Level sensitive - active high */
  164. LOG_IRQ("%s: set the SMI IRQ state to %d\n", __func__,
  165. level);
  166. ppc_set_irq(env, PPC_INTERRUPT_THERM, level);
  167. break;
  168. case PPC970_INPUT_MCP:
  169. /* Negative edge sensitive */
  170. /* XXX: TODO: actual reaction may depends on HID0 status
  171. * 603/604/740/750: check HID0[EMCP]
  172. */
  173. if (cur_level == 1 && level == 0) {
  174. LOG_IRQ("%s: raise machine check state\n",
  175. __func__);
  176. ppc_set_irq(env, PPC_INTERRUPT_MCK, 1);
  177. }
  178. break;
  179. case PPC970_INPUT_CKSTP:
  180. /* Level sensitive - active low */
  181. /* XXX: TODO: relay the signal to CKSTP_OUT pin */
  182. if (level) {
  183. LOG_IRQ("%s: stop the CPU\n", __func__);
  184. env->halted = 1;
  185. } else {
  186. LOG_IRQ("%s: restart the CPU\n", __func__);
  187. env->halted = 0;
  188. }
  189. break;
  190. case PPC970_INPUT_HRESET:
  191. /* Level sensitive - active low */
  192. if (level) {
  193. #if 0 // XXX: TOFIX
  194. LOG_IRQ("%s: reset the CPU\n", __func__);
  195. cpu_reset(env);
  196. #endif
  197. }
  198. break;
  199. case PPC970_INPUT_SRESET:
  200. LOG_IRQ("%s: set the RESET IRQ state to %d\n",
  201. __func__, level);
  202. ppc_set_irq(env, PPC_INTERRUPT_RESET, level);
  203. break;
  204. case PPC970_INPUT_TBEN:
  205. LOG_IRQ("%s: set the TBEN state to %d\n", __func__,
  206. level);
  207. /* XXX: TODO */
  208. break;
  209. default:
  210. /* Unknown pin - do nothing */
  211. LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
  212. return;
  213. }
  214. if (level)
  215. env->irq_input_state |= 1 << pin;
  216. else
  217. env->irq_input_state &= ~(1 << pin);
  218. }
  219. }
  220. void ppc970_irq_init (CPUState *env)
  221. {
  222. env->irq_inputs = (void **)qemu_allocate_irqs(&ppc970_set_irq, env,
  223. PPC970_INPUT_NB);
  224. }
  225. #endif /* defined(TARGET_PPC64) */
  226. /* PowerPC 40x internal IRQ controller */
  227. static void ppc40x_set_irq (void *opaque, int pin, int level)
  228. {
  229. CPUState *env = opaque;
  230. int cur_level;
  231. LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
  232. env, pin, level);
  233. cur_level = (env->irq_input_state >> pin) & 1;
  234. /* Don't generate spurious events */
  235. if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
  236. switch (pin) {
  237. case PPC40x_INPUT_RESET_SYS:
  238. if (level) {
  239. LOG_IRQ("%s: reset the PowerPC system\n",
  240. __func__);
  241. ppc40x_system_reset(env);
  242. }
  243. break;
  244. case PPC40x_INPUT_RESET_CHIP:
  245. if (level) {
  246. LOG_IRQ("%s: reset the PowerPC chip\n", __func__);
  247. ppc40x_chip_reset(env);
  248. }
  249. break;
  250. case PPC40x_INPUT_RESET_CORE:
  251. /* XXX: TODO: update DBSR[MRR] */
  252. if (level) {
  253. LOG_IRQ("%s: reset the PowerPC core\n", __func__);
  254. ppc40x_core_reset(env);
  255. }
  256. break;
  257. case PPC40x_INPUT_CINT:
  258. /* Level sensitive - active high */
  259. LOG_IRQ("%s: set the critical IRQ state to %d\n",
  260. __func__, level);
  261. ppc_set_irq(env, PPC_INTERRUPT_CEXT, level);
  262. break;
  263. case PPC40x_INPUT_INT:
  264. /* Level sensitive - active high */
  265. LOG_IRQ("%s: set the external IRQ state to %d\n",
  266. __func__, level);
  267. ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
  268. break;
  269. case PPC40x_INPUT_HALT:
  270. /* Level sensitive - active low */
  271. if (level) {
  272. LOG_IRQ("%s: stop the CPU\n", __func__);
  273. env->halted = 1;
  274. } else {
  275. LOG_IRQ("%s: restart the CPU\n", __func__);
  276. env->halted = 0;
  277. }
  278. break;
  279. case PPC40x_INPUT_DEBUG:
  280. /* Level sensitive - active high */
  281. LOG_IRQ("%s: set the debug pin state to %d\n",
  282. __func__, level);
  283. ppc_set_irq(env, PPC_INTERRUPT_DEBUG, level);
  284. break;
  285. default:
  286. /* Unknown pin - do nothing */
  287. LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
  288. return;
  289. }
  290. if (level)
  291. env->irq_input_state |= 1 << pin;
  292. else
  293. env->irq_input_state &= ~(1 << pin);
  294. }
  295. }
  296. void ppc40x_irq_init (CPUState *env)
  297. {
  298. env->irq_inputs = (void **)qemu_allocate_irqs(&ppc40x_set_irq,
  299. env, PPC40x_INPUT_NB);
  300. }
  301. /* PowerPC E500 internal IRQ controller */
  302. static void ppce500_set_irq (void *opaque, int pin, int level)
  303. {
  304. CPUState *env = opaque;
  305. int cur_level;
  306. LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
  307. env, pin, level);
  308. cur_level = (env->irq_input_state >> pin) & 1;
  309. /* Don't generate spurious events */
  310. if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
  311. switch (pin) {
  312. case PPCE500_INPUT_MCK:
  313. if (level) {
  314. LOG_IRQ("%s: reset the PowerPC system\n",
  315. __func__);
  316. qemu_system_reset_request();
  317. }
  318. break;
  319. case PPCE500_INPUT_RESET_CORE:
  320. if (level) {
  321. LOG_IRQ("%s: reset the PowerPC core\n", __func__);
  322. ppc_set_irq(env, PPC_INTERRUPT_MCK, level);
  323. }
  324. break;
  325. case PPCE500_INPUT_CINT:
  326. /* Level sensitive - active high */
  327. LOG_IRQ("%s: set the critical IRQ state to %d\n",
  328. __func__, level);
  329. ppc_set_irq(env, PPC_INTERRUPT_CEXT, level);
  330. break;
  331. case PPCE500_INPUT_INT:
  332. /* Level sensitive - active high */
  333. LOG_IRQ("%s: set the core IRQ state to %d\n",
  334. __func__, level);
  335. ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
  336. break;
  337. case PPCE500_INPUT_DEBUG:
  338. /* Level sensitive - active high */
  339. LOG_IRQ("%s: set the debug pin state to %d\n",
  340. __func__, level);
  341. ppc_set_irq(env, PPC_INTERRUPT_DEBUG, level);
  342. break;
  343. default:
  344. /* Unknown pin - do nothing */
  345. LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
  346. return;
  347. }
  348. if (level)
  349. env->irq_input_state |= 1 << pin;
  350. else
  351. env->irq_input_state &= ~(1 << pin);
  352. }
  353. }
  354. void ppce500_irq_init (CPUState *env)
  355. {
  356. env->irq_inputs = (void **)qemu_allocate_irqs(&ppce500_set_irq,
  357. env, PPCE500_INPUT_NB);
  358. }
  359. /*****************************************************************************/
  360. /* PowerPC time base and decrementer emulation */
  361. struct ppc_tb_t {
  362. /* Time base management */
  363. int64_t tb_offset; /* Compensation */
  364. int64_t atb_offset; /* Compensation */
  365. uint32_t tb_freq; /* TB frequency */
  366. /* Decrementer management */
  367. uint64_t decr_next; /* Tick for next decr interrupt */
  368. uint32_t decr_freq; /* decrementer frequency */
  369. struct QEMUTimer *decr_timer;
  370. /* Hypervisor decrementer management */
  371. uint64_t hdecr_next; /* Tick for next hdecr interrupt */
  372. struct QEMUTimer *hdecr_timer;
  373. uint64_t purr_load;
  374. uint64_t purr_start;
  375. void *opaque;
  376. };
  377. static always_inline uint64_t cpu_ppc_get_tb (ppc_tb_t *tb_env, uint64_t vmclk,
  378. int64_t tb_offset)
  379. {
  380. /* TB time in tb periods */
  381. return muldiv64(vmclk, tb_env->tb_freq, ticks_per_sec) + tb_offset;
  382. }
  383. uint32_t cpu_ppc_load_tbl (CPUState *env)
  384. {
  385. ppc_tb_t *tb_env = env->tb_env;
  386. uint64_t tb;
  387. tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
  388. LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
  389. return tb & 0xFFFFFFFF;
  390. }
  391. static always_inline uint32_t _cpu_ppc_load_tbu (CPUState *env)
  392. {
  393. ppc_tb_t *tb_env = env->tb_env;
  394. uint64_t tb;
  395. tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
  396. LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
  397. return tb >> 32;
  398. }
  399. uint32_t cpu_ppc_load_tbu (CPUState *env)
  400. {
  401. return _cpu_ppc_load_tbu(env);
  402. }
  403. static always_inline void cpu_ppc_store_tb (ppc_tb_t *tb_env, uint64_t vmclk,
  404. int64_t *tb_offsetp,
  405. uint64_t value)
  406. {
  407. *tb_offsetp = value - muldiv64(vmclk, tb_env->tb_freq, ticks_per_sec);
  408. LOG_TB("%s: tb %016" PRIx64 " offset %08" PRIx64 "\n",
  409. __func__, value, *tb_offsetp);
  410. }
  411. void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
  412. {
  413. ppc_tb_t *tb_env = env->tb_env;
  414. uint64_t tb;
  415. tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
  416. tb &= 0xFFFFFFFF00000000ULL;
  417. cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
  418. &tb_env->tb_offset, tb | (uint64_t)value);
  419. }
  420. static always_inline void _cpu_ppc_store_tbu (CPUState *env, uint32_t value)
  421. {
  422. ppc_tb_t *tb_env = env->tb_env;
  423. uint64_t tb;
  424. tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
  425. tb &= 0x00000000FFFFFFFFULL;
  426. cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
  427. &tb_env->tb_offset, ((uint64_t)value << 32) | tb);
  428. }
  429. void cpu_ppc_store_tbu (CPUState *env, uint32_t value)
  430. {
  431. _cpu_ppc_store_tbu(env, value);
  432. }
  433. uint32_t cpu_ppc_load_atbl (CPUState *env)
  434. {
  435. ppc_tb_t *tb_env = env->tb_env;
  436. uint64_t tb;
  437. tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
  438. LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
  439. return tb & 0xFFFFFFFF;
  440. }
  441. uint32_t cpu_ppc_load_atbu (CPUState *env)
  442. {
  443. ppc_tb_t *tb_env = env->tb_env;
  444. uint64_t tb;
  445. tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
  446. LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
  447. return tb >> 32;
  448. }
  449. void cpu_ppc_store_atbl (CPUState *env, uint32_t value)
  450. {
  451. ppc_tb_t *tb_env = env->tb_env;
  452. uint64_t tb;
  453. tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
  454. tb &= 0xFFFFFFFF00000000ULL;
  455. cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
  456. &tb_env->atb_offset, tb | (uint64_t)value);
  457. }
  458. void cpu_ppc_store_atbu (CPUState *env, uint32_t value)
  459. {
  460. ppc_tb_t *tb_env = env->tb_env;
  461. uint64_t tb;
  462. tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
  463. tb &= 0x00000000FFFFFFFFULL;
  464. cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
  465. &tb_env->atb_offset, ((uint64_t)value << 32) | tb);
  466. }
  467. static void cpu_ppc_tb_stop (CPUState *env)
  468. {
  469. ppc_tb_t *tb_env = env->tb_env;
  470. uint64_t tb, atb, vmclk;
  471. /* If the time base is already frozen, do nothing */
  472. if (tb_env->tb_freq != 0) {
  473. vmclk = qemu_get_clock(vm_clock);
  474. /* Get the time base */
  475. tb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->tb_offset);
  476. /* Get the alternate time base */
  477. atb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->atb_offset);
  478. /* Store the time base value (ie compute the current offset) */
  479. cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb);
  480. /* Store the alternate time base value (compute the current offset) */
  481. cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb);
  482. /* Set the time base frequency to zero */
  483. tb_env->tb_freq = 0;
  484. /* Now, the time bases are frozen to tb_offset / atb_offset value */
  485. }
  486. }
  487. static void cpu_ppc_tb_start (CPUState *env)
  488. {
  489. ppc_tb_t *tb_env = env->tb_env;
  490. uint64_t tb, atb, vmclk;
  491. /* If the time base is not frozen, do nothing */
  492. if (tb_env->tb_freq == 0) {
  493. vmclk = qemu_get_clock(vm_clock);
  494. /* Get the time base from tb_offset */
  495. tb = tb_env->tb_offset;
  496. /* Get the alternate time base from atb_offset */
  497. atb = tb_env->atb_offset;
  498. /* Restore the tb frequency from the decrementer frequency */
  499. tb_env->tb_freq = tb_env->decr_freq;
  500. /* Store the time base value */
  501. cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb);
  502. /* Store the alternate time base value */
  503. cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb);
  504. }
  505. }
  506. static always_inline uint32_t _cpu_ppc_load_decr (CPUState *env,
  507. uint64_t *next)
  508. {
  509. ppc_tb_t *tb_env = env->tb_env;
  510. uint32_t decr;
  511. int64_t diff;
  512. diff = tb_env->decr_next - qemu_get_clock(vm_clock);
  513. if (diff >= 0)
  514. decr = muldiv64(diff, tb_env->decr_freq, ticks_per_sec);
  515. else
  516. decr = -muldiv64(-diff, tb_env->decr_freq, ticks_per_sec);
  517. LOG_TB("%s: %08" PRIx32 "\n", __func__, decr);
  518. return decr;
  519. }
  520. uint32_t cpu_ppc_load_decr (CPUState *env)
  521. {
  522. ppc_tb_t *tb_env = env->tb_env;
  523. return _cpu_ppc_load_decr(env, &tb_env->decr_next);
  524. }
  525. uint32_t cpu_ppc_load_hdecr (CPUState *env)
  526. {
  527. ppc_tb_t *tb_env = env->tb_env;
  528. return _cpu_ppc_load_decr(env, &tb_env->hdecr_next);
  529. }
  530. uint64_t cpu_ppc_load_purr (CPUState *env)
  531. {
  532. ppc_tb_t *tb_env = env->tb_env;
  533. uint64_t diff;
  534. diff = qemu_get_clock(vm_clock) - tb_env->purr_start;
  535. return tb_env->purr_load + muldiv64(diff, tb_env->tb_freq, ticks_per_sec);
  536. }
  537. /* When decrementer expires,
  538. * all we need to do is generate or queue a CPU exception
  539. */
  540. static always_inline void cpu_ppc_decr_excp (CPUState *env)
  541. {
  542. /* Raise it */
  543. LOG_TB("raise decrementer exception\n");
  544. ppc_set_irq(env, PPC_INTERRUPT_DECR, 1);
  545. }
  546. static always_inline void cpu_ppc_hdecr_excp (CPUState *env)
  547. {
  548. /* Raise it */
  549. LOG_TB("raise decrementer exception\n");
  550. ppc_set_irq(env, PPC_INTERRUPT_HDECR, 1);
  551. }
  552. static void __cpu_ppc_store_decr (CPUState *env, uint64_t *nextp,
  553. struct QEMUTimer *timer,
  554. void (*raise_excp)(CPUState *),
  555. uint32_t decr, uint32_t value,
  556. int is_excp)
  557. {
  558. ppc_tb_t *tb_env = env->tb_env;
  559. uint64_t now, next;
  560. LOG_TB("%s: %08" PRIx32 " => %08" PRIx32 "\n", __func__,
  561. decr, value);
  562. now = qemu_get_clock(vm_clock);
  563. next = now + muldiv64(value, ticks_per_sec, tb_env->decr_freq);
  564. if (is_excp)
  565. next += *nextp - now;
  566. if (next == now)
  567. next++;
  568. *nextp = next;
  569. /* Adjust timer */
  570. qemu_mod_timer(timer, next);
  571. /* If we set a negative value and the decrementer was positive,
  572. * raise an exception.
  573. */
  574. if ((value & 0x80000000) && !(decr & 0x80000000))
  575. (*raise_excp)(env);
  576. }
  577. static always_inline void _cpu_ppc_store_decr (CPUState *env, uint32_t decr,
  578. uint32_t value, int is_excp)
  579. {
  580. ppc_tb_t *tb_env = env->tb_env;
  581. __cpu_ppc_store_decr(env, &tb_env->decr_next, tb_env->decr_timer,
  582. &cpu_ppc_decr_excp, decr, value, is_excp);
  583. }
  584. void cpu_ppc_store_decr (CPUState *env, uint32_t value)
  585. {
  586. _cpu_ppc_store_decr(env, cpu_ppc_load_decr(env), value, 0);
  587. }
  588. static void cpu_ppc_decr_cb (void *opaque)
  589. {
  590. _cpu_ppc_store_decr(opaque, 0x00000000, 0xFFFFFFFF, 1);
  591. }
  592. static always_inline void _cpu_ppc_store_hdecr (CPUState *env, uint32_t hdecr,
  593. uint32_t value, int is_excp)
  594. {
  595. ppc_tb_t *tb_env = env->tb_env;
  596. if (tb_env->hdecr_timer != NULL) {
  597. __cpu_ppc_store_decr(env, &tb_env->hdecr_next, tb_env->hdecr_timer,
  598. &cpu_ppc_hdecr_excp, hdecr, value, is_excp);
  599. }
  600. }
  601. void cpu_ppc_store_hdecr (CPUState *env, uint32_t value)
  602. {
  603. _cpu_ppc_store_hdecr(env, cpu_ppc_load_hdecr(env), value, 0);
  604. }
  605. static void cpu_ppc_hdecr_cb (void *opaque)
  606. {
  607. _cpu_ppc_store_hdecr(opaque, 0x00000000, 0xFFFFFFFF, 1);
  608. }
  609. void cpu_ppc_store_purr (CPUState *env, uint64_t value)
  610. {
  611. ppc_tb_t *tb_env = env->tb_env;
  612. tb_env->purr_load = value;
  613. tb_env->purr_start = qemu_get_clock(vm_clock);
  614. }
  615. static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
  616. {
  617. CPUState *env = opaque;
  618. ppc_tb_t *tb_env = env->tb_env;
  619. tb_env->tb_freq = freq;
  620. tb_env->decr_freq = freq;
  621. /* There is a bug in Linux 2.4 kernels:
  622. * if a decrementer exception is pending when it enables msr_ee at startup,
  623. * it's not ready to handle it...
  624. */
  625. _cpu_ppc_store_decr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
  626. _cpu_ppc_store_hdecr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
  627. cpu_ppc_store_purr(env, 0x0000000000000000ULL);
  628. }
  629. /* Set up (once) timebase frequency (in Hz) */
  630. clk_setup_cb cpu_ppc_tb_init (CPUState *env, uint32_t freq)
  631. {
  632. ppc_tb_t *tb_env;
  633. tb_env = qemu_mallocz(sizeof(ppc_tb_t));
  634. env->tb_env = tb_env;
  635. /* Create new timer */
  636. tb_env->decr_timer = qemu_new_timer(vm_clock, &cpu_ppc_decr_cb, env);
  637. if (0) {
  638. /* XXX: find a suitable condition to enable the hypervisor decrementer
  639. */
  640. tb_env->hdecr_timer = qemu_new_timer(vm_clock, &cpu_ppc_hdecr_cb, env);
  641. } else {
  642. tb_env->hdecr_timer = NULL;
  643. }
  644. cpu_ppc_set_tb_clk(env, freq);
  645. return &cpu_ppc_set_tb_clk;
  646. }
  647. /* Specific helpers for POWER & PowerPC 601 RTC */
  648. #if 0
  649. static clk_setup_cb cpu_ppc601_rtc_init (CPUState *env)
  650. {
  651. return cpu_ppc_tb_init(env, 7812500);
  652. }
  653. #endif
  654. void cpu_ppc601_store_rtcu (CPUState *env, uint32_t value)
  655. {
  656. _cpu_ppc_store_tbu(env, value);
  657. }
  658. uint32_t cpu_ppc601_load_rtcu (CPUState *env)
  659. {
  660. return _cpu_ppc_load_tbu(env);
  661. }
  662. void cpu_ppc601_store_rtcl (CPUState *env, uint32_t value)
  663. {
  664. cpu_ppc_store_tbl(env, value & 0x3FFFFF80);
  665. }
  666. uint32_t cpu_ppc601_load_rtcl (CPUState *env)
  667. {
  668. return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
  669. }
  670. /*****************************************************************************/
  671. /* Embedded PowerPC timers */
  672. /* PIT, FIT & WDT */
  673. typedef struct ppcemb_timer_t ppcemb_timer_t;
  674. struct ppcemb_timer_t {
  675. uint64_t pit_reload; /* PIT auto-reload value */
  676. uint64_t fit_next; /* Tick for next FIT interrupt */
  677. struct QEMUTimer *fit_timer;
  678. uint64_t wdt_next; /* Tick for next WDT interrupt */
  679. struct QEMUTimer *wdt_timer;
  680. };
  681. /* Fixed interval timer */
  682. static void cpu_4xx_fit_cb (void *opaque)
  683. {
  684. CPUState *env;
  685. ppc_tb_t *tb_env;
  686. ppcemb_timer_t *ppcemb_timer;
  687. uint64_t now, next;
  688. env = opaque;
  689. tb_env = env->tb_env;
  690. ppcemb_timer = tb_env->opaque;
  691. now = qemu_get_clock(vm_clock);
  692. switch ((env->spr[SPR_40x_TCR] >> 24) & 0x3) {
  693. case 0:
  694. next = 1 << 9;
  695. break;
  696. case 1:
  697. next = 1 << 13;
  698. break;
  699. case 2:
  700. next = 1 << 17;
  701. break;
  702. case 3:
  703. next = 1 << 21;
  704. break;
  705. default:
  706. /* Cannot occur, but makes gcc happy */
  707. return;
  708. }
  709. next = now + muldiv64(next, ticks_per_sec, tb_env->tb_freq);
  710. if (next == now)
  711. next++;
  712. qemu_mod_timer(ppcemb_timer->fit_timer, next);
  713. env->spr[SPR_40x_TSR] |= 1 << 26;
  714. if ((env->spr[SPR_40x_TCR] >> 23) & 0x1)
  715. ppc_set_irq(env, PPC_INTERRUPT_FIT, 1);
  716. LOG_TB("%s: ir %d TCR " ADDRX " TSR " ADDRX "\n", __func__,
  717. (int)((env->spr[SPR_40x_TCR] >> 23) & 0x1),
  718. env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
  719. }
  720. /* Programmable interval timer */
  721. static void start_stop_pit (CPUState *env, ppc_tb_t *tb_env, int is_excp)
  722. {
  723. ppcemb_timer_t *ppcemb_timer;
  724. uint64_t now, next;
  725. ppcemb_timer = tb_env->opaque;
  726. if (ppcemb_timer->pit_reload <= 1 ||
  727. !((env->spr[SPR_40x_TCR] >> 26) & 0x1) ||
  728. (is_excp && !((env->spr[SPR_40x_TCR] >> 22) & 0x1))) {
  729. /* Stop PIT */
  730. LOG_TB("%s: stop PIT\n", __func__);
  731. qemu_del_timer(tb_env->decr_timer);
  732. } else {
  733. LOG_TB("%s: start PIT %016" PRIx64 "\n",
  734. __func__, ppcemb_timer->pit_reload);
  735. now = qemu_get_clock(vm_clock);
  736. next = now + muldiv64(ppcemb_timer->pit_reload,
  737. ticks_per_sec, tb_env->decr_freq);
  738. if (is_excp)
  739. next += tb_env->decr_next - now;
  740. if (next == now)
  741. next++;
  742. qemu_mod_timer(tb_env->decr_timer, next);
  743. tb_env->decr_next = next;
  744. }
  745. }
  746. static void cpu_4xx_pit_cb (void *opaque)
  747. {
  748. CPUState *env;
  749. ppc_tb_t *tb_env;
  750. ppcemb_timer_t *ppcemb_timer;
  751. env = opaque;
  752. tb_env = env->tb_env;
  753. ppcemb_timer = tb_env->opaque;
  754. env->spr[SPR_40x_TSR] |= 1 << 27;
  755. if ((env->spr[SPR_40x_TCR] >> 26) & 0x1)
  756. ppc_set_irq(env, PPC_INTERRUPT_PIT, 1);
  757. start_stop_pit(env, tb_env, 1);
  758. LOG_TB("%s: ar %d ir %d TCR " ADDRX " TSR " ADDRX " "
  759. "%016" PRIx64 "\n", __func__,
  760. (int)((env->spr[SPR_40x_TCR] >> 22) & 0x1),
  761. (int)((env->spr[SPR_40x_TCR] >> 26) & 0x1),
  762. env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR],
  763. ppcemb_timer->pit_reload);
  764. }
  765. /* Watchdog timer */
  766. static void cpu_4xx_wdt_cb (void *opaque)
  767. {
  768. CPUState *env;
  769. ppc_tb_t *tb_env;
  770. ppcemb_timer_t *ppcemb_timer;
  771. uint64_t now, next;
  772. env = opaque;
  773. tb_env = env->tb_env;
  774. ppcemb_timer = tb_env->opaque;
  775. now = qemu_get_clock(vm_clock);
  776. switch ((env->spr[SPR_40x_TCR] >> 30) & 0x3) {
  777. case 0:
  778. next = 1 << 17;
  779. break;
  780. case 1:
  781. next = 1 << 21;
  782. break;
  783. case 2:
  784. next = 1 << 25;
  785. break;
  786. case 3:
  787. next = 1 << 29;
  788. break;
  789. default:
  790. /* Cannot occur, but makes gcc happy */
  791. return;
  792. }
  793. next = now + muldiv64(next, ticks_per_sec, tb_env->decr_freq);
  794. if (next == now)
  795. next++;
  796. LOG_TB("%s: TCR " ADDRX " TSR " ADDRX "\n", __func__,
  797. env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
  798. switch ((env->spr[SPR_40x_TSR] >> 30) & 0x3) {
  799. case 0x0:
  800. case 0x1:
  801. qemu_mod_timer(ppcemb_timer->wdt_timer, next);
  802. ppcemb_timer->wdt_next = next;
  803. env->spr[SPR_40x_TSR] |= 1 << 31;
  804. break;
  805. case 0x2:
  806. qemu_mod_timer(ppcemb_timer->wdt_timer, next);
  807. ppcemb_timer->wdt_next = next;
  808. env->spr[SPR_40x_TSR] |= 1 << 30;
  809. if ((env->spr[SPR_40x_TCR] >> 27) & 0x1)
  810. ppc_set_irq(env, PPC_INTERRUPT_WDT, 1);
  811. break;
  812. case 0x3:
  813. env->spr[SPR_40x_TSR] &= ~0x30000000;
  814. env->spr[SPR_40x_TSR] |= env->spr[SPR_40x_TCR] & 0x30000000;
  815. switch ((env->spr[SPR_40x_TCR] >> 28) & 0x3) {
  816. case 0x0:
  817. /* No reset */
  818. break;
  819. case 0x1: /* Core reset */
  820. ppc40x_core_reset(env);
  821. break;
  822. case 0x2: /* Chip reset */
  823. ppc40x_chip_reset(env);
  824. break;
  825. case 0x3: /* System reset */
  826. ppc40x_system_reset(env);
  827. break;
  828. }
  829. }
  830. }
  831. void store_40x_pit (CPUState *env, target_ulong val)
  832. {
  833. ppc_tb_t *tb_env;
  834. ppcemb_timer_t *ppcemb_timer;
  835. tb_env = env->tb_env;
  836. ppcemb_timer = tb_env->opaque;
  837. LOG_TB("%s val" ADDRX "\n", __func__, val);
  838. ppcemb_timer->pit_reload = val;
  839. start_stop_pit(env, tb_env, 0);
  840. }
  841. target_ulong load_40x_pit (CPUState *env)
  842. {
  843. return cpu_ppc_load_decr(env);
  844. }
  845. void store_booke_tsr (CPUState *env, target_ulong val)
  846. {
  847. LOG_TB("%s: val " ADDRX "\n", __func__, val);
  848. env->spr[SPR_40x_TSR] &= ~(val & 0xFC000000);
  849. if (val & 0x80000000)
  850. ppc_set_irq(env, PPC_INTERRUPT_PIT, 0);
  851. }
  852. void store_booke_tcr (CPUState *env, target_ulong val)
  853. {
  854. ppc_tb_t *tb_env;
  855. tb_env = env->tb_env;
  856. LOG_TB("%s: val " ADDRX "\n", __func__, val);
  857. env->spr[SPR_40x_TCR] = val & 0xFFC00000;
  858. start_stop_pit(env, tb_env, 1);
  859. cpu_4xx_wdt_cb(env);
  860. }
  861. static void ppc_emb_set_tb_clk (void *opaque, uint32_t freq)
  862. {
  863. CPUState *env = opaque;
  864. ppc_tb_t *tb_env = env->tb_env;
  865. LOG_TB("%s set new frequency to %" PRIu32 "\n", __func__,
  866. freq);
  867. tb_env->tb_freq = freq;
  868. tb_env->decr_freq = freq;
  869. /* XXX: we should also update all timers */
  870. }
  871. clk_setup_cb ppc_emb_timers_init (CPUState *env, uint32_t freq)
  872. {
  873. ppc_tb_t *tb_env;
  874. ppcemb_timer_t *ppcemb_timer;
  875. tb_env = qemu_mallocz(sizeof(ppc_tb_t));
  876. env->tb_env = tb_env;
  877. ppcemb_timer = qemu_mallocz(sizeof(ppcemb_timer_t));
  878. tb_env->tb_freq = freq;
  879. tb_env->decr_freq = freq;
  880. tb_env->opaque = ppcemb_timer;
  881. LOG_TB("%s freq %" PRIu32 "\n", __func__, freq);
  882. if (ppcemb_timer != NULL) {
  883. /* We use decr timer for PIT */
  884. tb_env->decr_timer = qemu_new_timer(vm_clock, &cpu_4xx_pit_cb, env);
  885. ppcemb_timer->fit_timer =
  886. qemu_new_timer(vm_clock, &cpu_4xx_fit_cb, env);
  887. ppcemb_timer->wdt_timer =
  888. qemu_new_timer(vm_clock, &cpu_4xx_wdt_cb, env);
  889. }
  890. return &ppc_emb_set_tb_clk;
  891. }
  892. /*****************************************************************************/
  893. /* Embedded PowerPC Device Control Registers */
  894. typedef struct ppc_dcrn_t ppc_dcrn_t;
  895. struct ppc_dcrn_t {
  896. dcr_read_cb dcr_read;
  897. dcr_write_cb dcr_write;
  898. void *opaque;
  899. };
  900. /* XXX: on 460, DCR addresses are 32 bits wide,
  901. * using DCRIPR to get the 22 upper bits of the DCR address
  902. */
  903. #define DCRN_NB 1024
  904. struct ppc_dcr_t {
  905. ppc_dcrn_t dcrn[DCRN_NB];
  906. int (*read_error)(int dcrn);
  907. int (*write_error)(int dcrn);
  908. };
  909. int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, target_ulong *valp)
  910. {
  911. ppc_dcrn_t *dcr;
  912. if (dcrn < 0 || dcrn >= DCRN_NB)
  913. goto error;
  914. dcr = &dcr_env->dcrn[dcrn];
  915. if (dcr->dcr_read == NULL)
  916. goto error;
  917. *valp = (*dcr->dcr_read)(dcr->opaque, dcrn);
  918. return 0;
  919. error:
  920. if (dcr_env->read_error != NULL)
  921. return (*dcr_env->read_error)(dcrn);
  922. return -1;
  923. }
  924. int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val)
  925. {
  926. ppc_dcrn_t *dcr;
  927. if (dcrn < 0 || dcrn >= DCRN_NB)
  928. goto error;
  929. dcr = &dcr_env->dcrn[dcrn];
  930. if (dcr->dcr_write == NULL)
  931. goto error;
  932. (*dcr->dcr_write)(dcr->opaque, dcrn, val);
  933. return 0;
  934. error:
  935. if (dcr_env->write_error != NULL)
  936. return (*dcr_env->write_error)(dcrn);
  937. return -1;
  938. }
  939. int ppc_dcr_register (CPUState *env, int dcrn, void *opaque,
  940. dcr_read_cb dcr_read, dcr_write_cb dcr_write)
  941. {
  942. ppc_dcr_t *dcr_env;
  943. ppc_dcrn_t *dcr;
  944. dcr_env = env->dcr_env;
  945. if (dcr_env == NULL)
  946. return -1;
  947. if (dcrn < 0 || dcrn >= DCRN_NB)
  948. return -1;
  949. dcr = &dcr_env->dcrn[dcrn];
  950. if (dcr->opaque != NULL ||
  951. dcr->dcr_read != NULL ||
  952. dcr->dcr_write != NULL)
  953. return -1;
  954. dcr->opaque = opaque;
  955. dcr->dcr_read = dcr_read;
  956. dcr->dcr_write = dcr_write;
  957. return 0;
  958. }
  959. int ppc_dcr_init (CPUState *env, int (*read_error)(int dcrn),
  960. int (*write_error)(int dcrn))
  961. {
  962. ppc_dcr_t *dcr_env;
  963. dcr_env = qemu_mallocz(sizeof(ppc_dcr_t));
  964. dcr_env->read_error = read_error;
  965. dcr_env->write_error = write_error;
  966. env->dcr_env = dcr_env;
  967. return 0;
  968. }
  969. #if 0
  970. /*****************************************************************************/
  971. /* Handle system reset (for now, just stop emulation) */
  972. void cpu_ppc_reset (CPUState *env)
  973. {
  974. printf("Reset asked... Stop emulation\n");
  975. abort();
  976. }
  977. #endif
  978. /*****************************************************************************/
  979. /* Debug port */
  980. void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val)
  981. {
  982. addr &= 0xF;
  983. switch (addr) {
  984. case 0:
  985. printf("%c", val);
  986. break;
  987. case 1:
  988. printf("\n");
  989. fflush(stdout);
  990. break;
  991. case 2:
  992. printf("Set loglevel to %04" PRIx32 "\n", val);
  993. cpu_set_log(val | 0x100);
  994. break;
  995. }
  996. }
  997. /*****************************************************************************/
  998. /* NVRAM helpers */
  999. static inline uint32_t nvram_read (nvram_t *nvram, uint32_t addr)
  1000. {
  1001. return (*nvram->read_fn)(nvram->opaque, addr);;
  1002. }
  1003. static inline void nvram_write (nvram_t *nvram, uint32_t addr, uint32_t val)
  1004. {
  1005. (*nvram->write_fn)(nvram->opaque, addr, val);
  1006. }
  1007. void NVRAM_set_byte (nvram_t *nvram, uint32_t addr, uint8_t value)
  1008. {
  1009. nvram_write(nvram, addr, value);
  1010. }
  1011. uint8_t NVRAM_get_byte (nvram_t *nvram, uint32_t addr)
  1012. {
  1013. return nvram_read(nvram, addr);
  1014. }
  1015. void NVRAM_set_word (nvram_t *nvram, uint32_t addr, uint16_t value)
  1016. {
  1017. nvram_write(nvram, addr, value >> 8);
  1018. nvram_write(nvram, addr + 1, value & 0xFF);
  1019. }
  1020. uint16_t NVRAM_get_word (nvram_t *nvram, uint32_t addr)
  1021. {
  1022. uint16_t tmp;
  1023. tmp = nvram_read(nvram, addr) << 8;
  1024. tmp |= nvram_read(nvram, addr + 1);
  1025. return tmp;
  1026. }
  1027. void NVRAM_set_lword (nvram_t *nvram, uint32_t addr, uint32_t value)
  1028. {
  1029. nvram_write(nvram, addr, value >> 24);
  1030. nvram_write(nvram, addr + 1, (value >> 16) & 0xFF);
  1031. nvram_write(nvram, addr + 2, (value >> 8) & 0xFF);
  1032. nvram_write(nvram, addr + 3, value & 0xFF);
  1033. }
  1034. uint32_t NVRAM_get_lword (nvram_t *nvram, uint32_t addr)
  1035. {
  1036. uint32_t tmp;
  1037. tmp = nvram_read(nvram, addr) << 24;
  1038. tmp |= nvram_read(nvram, addr + 1) << 16;
  1039. tmp |= nvram_read(nvram, addr + 2) << 8;
  1040. tmp |= nvram_read(nvram, addr + 3);
  1041. return tmp;
  1042. }
  1043. void NVRAM_set_string (nvram_t *nvram, uint32_t addr,
  1044. const char *str, uint32_t max)
  1045. {
  1046. int i;
  1047. for (i = 0; i < max && str[i] != '\0'; i++) {
  1048. nvram_write(nvram, addr + i, str[i]);
  1049. }
  1050. nvram_write(nvram, addr + i, str[i]);
  1051. nvram_write(nvram, addr + max - 1, '\0');
  1052. }
  1053. int NVRAM_get_string (nvram_t *nvram, uint8_t *dst, uint16_t addr, int max)
  1054. {
  1055. int i;
  1056. memset(dst, 0, max);
  1057. for (i = 0; i < max; i++) {
  1058. dst[i] = NVRAM_get_byte(nvram, addr + i);
  1059. if (dst[i] == '\0')
  1060. break;
  1061. }
  1062. return i;
  1063. }
  1064. static uint16_t NVRAM_crc_update (uint16_t prev, uint16_t value)
  1065. {
  1066. uint16_t tmp;
  1067. uint16_t pd, pd1, pd2;
  1068. tmp = prev >> 8;
  1069. pd = prev ^ value;
  1070. pd1 = pd & 0x000F;
  1071. pd2 = ((pd >> 4) & 0x000F) ^ pd1;
  1072. tmp ^= (pd1 << 3) | (pd1 << 8);
  1073. tmp ^= pd2 | (pd2 << 7) | (pd2 << 12);
  1074. return tmp;
  1075. }
  1076. static uint16_t NVRAM_compute_crc (nvram_t *nvram, uint32_t start, uint32_t count)
  1077. {
  1078. uint32_t i;
  1079. uint16_t crc = 0xFFFF;
  1080. int odd;
  1081. odd = count & 1;
  1082. count &= ~1;
  1083. for (i = 0; i != count; i++) {
  1084. crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i));
  1085. }
  1086. if (odd) {
  1087. crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8);
  1088. }
  1089. return crc;
  1090. }
  1091. #define CMDLINE_ADDR 0x017ff000
  1092. int PPC_NVRAM_set_params (nvram_t *nvram, uint16_t NVRAM_size,
  1093. const char *arch,
  1094. uint32_t RAM_size, int boot_device,
  1095. uint32_t kernel_image, uint32_t kernel_size,
  1096. const char *cmdline,
  1097. uint32_t initrd_image, uint32_t initrd_size,
  1098. uint32_t NVRAM_image,
  1099. int width, int height, int depth)
  1100. {
  1101. uint16_t crc;
  1102. /* Set parameters for Open Hack'Ware BIOS */
  1103. NVRAM_set_string(nvram, 0x00, "QEMU_BIOS", 16);
  1104. NVRAM_set_lword(nvram, 0x10, 0x00000002); /* structure v2 */
  1105. NVRAM_set_word(nvram, 0x14, NVRAM_size);
  1106. NVRAM_set_string(nvram, 0x20, arch, 16);
  1107. NVRAM_set_lword(nvram, 0x30, RAM_size);
  1108. NVRAM_set_byte(nvram, 0x34, boot_device);
  1109. NVRAM_set_lword(nvram, 0x38, kernel_image);
  1110. NVRAM_set_lword(nvram, 0x3C, kernel_size);
  1111. if (cmdline) {
  1112. /* XXX: put the cmdline in NVRAM too ? */
  1113. strcpy((char *)(phys_ram_base + CMDLINE_ADDR), cmdline);
  1114. NVRAM_set_lword(nvram, 0x40, CMDLINE_ADDR);
  1115. NVRAM_set_lword(nvram, 0x44, strlen(cmdline));
  1116. } else {
  1117. NVRAM_set_lword(nvram, 0x40, 0);
  1118. NVRAM_set_lword(nvram, 0x44, 0);
  1119. }
  1120. NVRAM_set_lword(nvram, 0x48, initrd_image);
  1121. NVRAM_set_lword(nvram, 0x4C, initrd_size);
  1122. NVRAM_set_lword(nvram, 0x50, NVRAM_image);
  1123. NVRAM_set_word(nvram, 0x54, width);
  1124. NVRAM_set_word(nvram, 0x56, height);
  1125. NVRAM_set_word(nvram, 0x58, depth);
  1126. crc = NVRAM_compute_crc(nvram, 0x00, 0xF8);
  1127. NVRAM_set_word(nvram, 0xFC, crc);
  1128. return 0;
  1129. }