arch/powerpc/platforms/ps3/htab.c

Source file repositories/reference/linux-study-clean/arch/powerpc/platforms/ps3/htab.c

File Facts

System
Linux kernel
Corpus path
arch/powerpc/platforms/ps3/htab.c
Extension
.c
Size
5005 bytes
Lines
196
Domain
Architecture Layer
Bucket
arch/powerpc
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0-only
/*
 *  PS3 pagetable management routines.
 *
 *  Copyright (C) 2006 Sony Computer Entertainment Inc.
 *  Copyright 2006, 2007 Sony Corporation
 */

#include <linux/kernel.h>
#include <linux/memblock.h>

#include <asm/machdep.h>
#include <asm/udbg.h>
#include <asm/lv1call.h>
#include <asm/ps3fb.h>

#define PS3_VERBOSE_RESULT
#include "platform.h"

/**
 * enum lpar_vas_id - id of LPAR virtual address space.
 * @lpar_vas_id_current: Current selected virtual address space
 *
 * Identify the target LPAR address space.
 */

enum ps3_lpar_vas_id {
	PS3_LPAR_VAS_ID_CURRENT = 0,
};


static DEFINE_SPINLOCK(ps3_htab_lock);

static long ps3_hpte_insert(unsigned long hpte_group, unsigned long vpn,
	unsigned long pa, unsigned long rflags, unsigned long vflags,
	int psize, int apsize, int ssize)
{
	int result;
	u64 hpte_v, hpte_r;
	u64 inserted_index;
	u64 evicted_v, evicted_r;
	u64 hpte_v_array[4], hpte_rs;
	unsigned long flags;
	long ret = -1;

	/*
	 * lv1_insert_htab_entry() will search for victim
	 * entry in both primary and secondary pte group
	 */
	vflags &= ~HPTE_V_SECONDARY;

	hpte_v = hpte_encode_v(vpn, psize, apsize, ssize) | vflags | HPTE_V_VALID;
	hpte_r = hpte_encode_r(ps3_mm_phys_to_lpar(pa), psize, apsize) | rflags;

	spin_lock_irqsave(&ps3_htab_lock, flags);

	/* talk hvc to replace entries BOLTED == 0 */
	result = lv1_insert_htab_entry(PS3_LPAR_VAS_ID_CURRENT, hpte_group,
				       hpte_v, hpte_r,
				       HPTE_V_BOLTED, 0,
				       &inserted_index,
				       &evicted_v, &evicted_r);

	if (result) {
		/* all entries bolted !*/
		pr_info("%s:result=%s vpn=%lx pa=%lx ix=%lx v=%llx r=%llx\n",
			__func__, ps3_result(result), vpn, pa, hpte_group,
			hpte_v, hpte_r);
		BUG();
	}

	/*
	 * see if the entry is inserted into secondary pteg
	 */
	result = lv1_read_htab_entries(PS3_LPAR_VAS_ID_CURRENT,
				       inserted_index & ~0x3UL,
				       &hpte_v_array[0], &hpte_v_array[1],
				       &hpte_v_array[2], &hpte_v_array[3],
				       &hpte_rs);
	BUG_ON(result);

	if (hpte_v_array[inserted_index % 4] & HPTE_V_SECONDARY)
		ret = (inserted_index & 7) | (1 << 3);
	else
		ret = inserted_index & 7;

	spin_unlock_irqrestore(&ps3_htab_lock, flags);

	return ret;
}

Annotation

Implementation Notes